From 957afb669f0c7d6c8ce1e9c6a26011d1ba08e03f Mon Sep 17 00:00:00 2001 From: Stijn Frishert Date: Mon, 10 Feb 2025 16:40:59 +0100 Subject: [PATCH] Delegate tao key events to tauri --- .changes/expose-keyboard-inputs.md | 5 + Cargo.lock | 1 + crates/tauri-runtime-wry/src/keyboard.rs | 559 +++++++++++++++++++++++ crates/tauri-runtime-wry/src/lib.rs | 6 + crates/tauri-runtime/Cargo.toml | 1 + crates/tauri-runtime/src/keyboard.rs | 18 + crates/tauri-runtime/src/lib.rs | 1 + crates/tauri-runtime/src/window.rs | 5 + crates/tauri/src/app.rs | 4 + crates/tauri/src/manager/window.rs | 4 + 10 files changed, 604 insertions(+) create mode 100644 .changes/expose-keyboard-inputs.md create mode 100644 crates/tauri-runtime-wry/src/keyboard.rs create mode 100644 crates/tauri-runtime/src/keyboard.rs diff --git a/.changes/expose-keyboard-inputs.md b/.changes/expose-keyboard-inputs.md new file mode 100644 index 000000000000..209bc4582d72 --- /dev/null +++ b/.changes/expose-keyboard-inputs.md @@ -0,0 +1,5 @@ +--- +tauri: 'minor:feat' +--- + +Expose window keyboard events from `tao`, as `WindowEvent::KeyboardInput`. diff --git a/Cargo.lock b/Cargo.lock index 28031d69f68f..32a2e03dc9a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9395,6 +9395,7 @@ dependencies = [ "gtk", "http 1.2.0", "jni", + "keyboard-types", "raw-window-handle", "serde", "serde_json", diff --git a/crates/tauri-runtime-wry/src/keyboard.rs b/crates/tauri-runtime-wry/src/keyboard.rs new file mode 100644 index 000000000000..2ba533b81601 --- /dev/null +++ b/crates/tauri-runtime-wry/src/keyboard.rs @@ -0,0 +1,559 @@ +use tao::{ + event::{ElementState as TaoElementState, KeyEvent as TaoKeyEvent}, + keyboard::{Key as TaoKey, KeyCode as TaoKeyCode, KeyLocation as TaoKeyLocation}, +}; +use tauri_runtime::keyboard::{Code, Key, KeyState, KeyboardEvent, Location}; + +pub(crate) fn convert_key_event(event: &TaoKeyEvent) -> KeyboardEvent { + let state = convert_key_state(&event.state).expect("Unsupported key state"); + let key = convert_key(&event.logical_key); + let code = convert_key_code(&event.physical_key); + let location = convert_location(&event.location).expect("Unsupported key location"); + + KeyboardEvent { + state, + key, + code, + location, + repeat: event.repeat, + } +} + +fn convert_key(key: &TaoKey<'_>) -> Key { + match key { + TaoKey::Character(c) => Key::Character(c.to_string()), + TaoKey::Unidentified(_) => Key::Unidentified, + TaoKey::Dead(_) => Key::Dead, + TaoKey::Alt => Key::Alt, + TaoKey::AltGraph => Key::AltGraph, + TaoKey::CapsLock => Key::CapsLock, + TaoKey::Control => Key::Control, + TaoKey::Fn => Key::Fn, + TaoKey::FnLock => Key::FnLock, + TaoKey::NumLock => Key::NumLock, + TaoKey::ScrollLock => Key::ScrollLock, + TaoKey::Shift => Key::Shift, + TaoKey::Symbol => Key::Symbol, + TaoKey::SymbolLock => Key::SymbolLock, + TaoKey::Hyper => Key::Hyper, + // What Tao calls super, the web at calls meta. + // It's the key that represents the Windows logo on Windows, and the Command key (⌘) on Mac. + TaoKey::Super => Key::Meta, + TaoKey::Enter => Key::Enter, + TaoKey::Tab => Key::Tab, + // TaoKey has space, but Key does not. + // According to whitespace is encoded as regular + // strings, and so we convert to Key::Character here with a space value. + TaoKey::Space => Key::Character(String::from("\u{0020}")), + TaoKey::ArrowDown => Key::ArrowDown, + TaoKey::ArrowLeft => Key::ArrowLeft, + TaoKey::ArrowRight => Key::ArrowRight, + TaoKey::ArrowUp => Key::ArrowUp, + TaoKey::End => Key::End, + TaoKey::Home => Key::Home, + TaoKey::PageDown => Key::PageDown, + TaoKey::PageUp => Key::PageUp, + TaoKey::Backspace => Key::Backspace, + TaoKey::Clear => Key::Clear, + TaoKey::Copy => Key::Copy, + TaoKey::Cut => Key::Cut, + TaoKey::Delete => Key::Delete, + TaoKey::EraseEof => Key::EraseEof, + TaoKey::ExSel => Key::ExSel, + TaoKey::Insert => Key::Insert, + TaoKey::Paste => Key::Paste, + TaoKey::Redo => Key::Redo, + TaoKey::Undo => Key::Undo, + TaoKey::Accept => Key::Accept, + TaoKey::Again => Key::Again, + TaoKey::Attn => Key::Attn, + TaoKey::Cancel => Key::Cancel, + TaoKey::ContextMenu => Key::ContextMenu, + TaoKey::Escape => Key::Escape, + TaoKey::Execute => Key::Execute, + TaoKey::Find => Key::Find, + TaoKey::Help => Key::Help, + TaoKey::Pause => Key::Pause, + TaoKey::Play => Key::Play, + TaoKey::Props => Key::Props, + TaoKey::Select => Key::Select, + TaoKey::ZoomIn => Key::ZoomIn, + TaoKey::ZoomOut => Key::ZoomOut, + TaoKey::BrightnessDown => Key::BrightnessDown, + TaoKey::BrightnessUp => Key::BrightnessUp, + TaoKey::Eject => Key::Eject, + TaoKey::LogOff => Key::LogOff, + TaoKey::Power => Key::Power, + TaoKey::PowerOff => Key::PowerOff, + TaoKey::PrintScreen => Key::PrintScreen, + TaoKey::Hibernate => Key::Hibernate, + TaoKey::Standby => Key::Standby, + TaoKey::WakeUp => Key::WakeUp, + TaoKey::AllCandidates => Key::AllCandidates, + TaoKey::Alphanumeric => Key::Alphanumeric, + TaoKey::CodeInput => Key::CodeInput, + TaoKey::Compose => Key::Compose, + TaoKey::Convert => Key::Convert, + TaoKey::FinalMode => Key::FinalMode, + TaoKey::GroupFirst => Key::GroupFirst, + TaoKey::GroupLast => Key::GroupLast, + TaoKey::GroupNext => Key::GroupNext, + TaoKey::GroupPrevious => Key::GroupPrevious, + TaoKey::ModeChange => Key::ModeChange, + TaoKey::NextCandidate => Key::NextCandidate, + TaoKey::NonConvert => Key::NonConvert, + TaoKey::PreviousCandidate => Key::PreviousCandidate, + TaoKey::Process => Key::Process, + TaoKey::SingleCandidate => Key::SingleCandidate, + TaoKey::HangulMode => Key::HangulMode, + TaoKey::HanjaMode => Key::HanjaMode, + TaoKey::JunjaMode => Key::JunjaMode, + TaoKey::Eisu => Key::Eisu, + TaoKey::Hankaku => Key::Hankaku, + TaoKey::Hiragana => Key::Hiragana, + TaoKey::HiraganaKatakana => Key::HiraganaKatakana, + TaoKey::KanaMode => Key::KanaMode, + TaoKey::KanjiMode => Key::KanjiMode, + TaoKey::Katakana => Key::Katakana, + TaoKey::Romaji => Key::Romaji, + TaoKey::Zenkaku => Key::Zenkaku, + TaoKey::ZenkakuHankaku => Key::ZenkakuHankaku, + TaoKey::Soft1 => Key::Soft1, + TaoKey::Soft2 => Key::Soft2, + TaoKey::Soft3 => Key::Soft3, + TaoKey::Soft4 => Key::Soft4, + TaoKey::ChannelDown => Key::ChannelDown, + TaoKey::ChannelUp => Key::ChannelUp, + TaoKey::Close => Key::Close, + TaoKey::MailForward => Key::MailForward, + TaoKey::MailReply => Key::MailReply, + TaoKey::MailSend => Key::MailSend, + TaoKey::MediaClose => Key::MediaClose, + TaoKey::MediaFastForward => Key::MediaFastForward, + TaoKey::MediaPause => Key::MediaPause, + TaoKey::MediaPlay => Key::MediaPlay, + TaoKey::MediaPlayPause => Key::MediaPlayPause, + TaoKey::MediaRecord => Key::MediaRecord, + TaoKey::MediaRewind => Key::MediaRewind, + TaoKey::MediaStop => Key::MediaStop, + TaoKey::MediaTrackNext => Key::MediaTrackNext, + TaoKey::MediaTrackPrevious => Key::MediaTrackPrevious, + TaoKey::New => Key::New, + TaoKey::Open => Key::Open, + TaoKey::Print => Key::Print, + TaoKey::Save => Key::Save, + TaoKey::SpellCheck => Key::SpellCheck, + TaoKey::Key11 => Key::Key11, + TaoKey::Key12 => Key::Key12, + TaoKey::AudioBalanceLeft => Key::AudioBalanceLeft, + TaoKey::AudioBalanceRight => Key::AudioBalanceRight, + TaoKey::AudioBassBoostDown => Key::AudioBassBoostDown, + TaoKey::AudioBassBoostToggle => Key::AudioBassBoostToggle, + TaoKey::AudioBassBoostUp => Key::AudioBassBoostUp, + TaoKey::AudioFaderFront => Key::AudioFaderFront, + TaoKey::AudioFaderRear => Key::AudioFaderRear, + TaoKey::AudioSurroundModeNext => Key::AudioSurroundModeNext, + TaoKey::AudioTrebleDown => Key::AudioTrebleDown, + TaoKey::AudioTrebleUp => Key::AudioTrebleUp, + TaoKey::AudioVolumeDown => Key::AudioVolumeDown, + TaoKey::AudioVolumeUp => Key::AudioVolumeUp, + TaoKey::AudioVolumeMute => Key::AudioVolumeMute, + TaoKey::MicrophoneToggle => Key::MicrophoneToggle, + TaoKey::MicrophoneVolumeDown => Key::MicrophoneVolumeDown, + TaoKey::MicrophoneVolumeUp => Key::MicrophoneVolumeUp, + TaoKey::MicrophoneVolumeMute => Key::MicrophoneVolumeMute, + TaoKey::SpeechCorrectionList => Key::SpeechCorrectionList, + TaoKey::SpeechInputToggle => Key::SpeechInputToggle, + TaoKey::LaunchApplication1 => Key::LaunchApplication1, + TaoKey::LaunchApplication2 => Key::LaunchApplication2, + TaoKey::LaunchCalendar => Key::LaunchCalendar, + TaoKey::LaunchContacts => Key::LaunchContacts, + TaoKey::LaunchMail => Key::LaunchMail, + TaoKey::LaunchMediaPlayer => Key::LaunchMediaPlayer, + TaoKey::LaunchMusicPlayer => Key::LaunchMusicPlayer, + TaoKey::LaunchPhone => Key::LaunchPhone, + TaoKey::LaunchScreenSaver => Key::LaunchScreenSaver, + TaoKey::LaunchSpreadsheet => Key::LaunchSpreadsheet, + TaoKey::LaunchWebBrowser => Key::LaunchWebBrowser, + TaoKey::LaunchWebCam => Key::LaunchWebCam, + TaoKey::LaunchWordProcessor => Key::LaunchWordProcessor, + TaoKey::BrowserBack => Key::BrowserBack, + TaoKey::BrowserFavorites => Key::BrowserFavorites, + TaoKey::BrowserForward => Key::BrowserForward, + TaoKey::BrowserHome => Key::BrowserHome, + TaoKey::BrowserRefresh => Key::BrowserRefresh, + TaoKey::BrowserSearch => Key::BrowserSearch, + TaoKey::BrowserStop => Key::BrowserStop, + TaoKey::AppSwitch => Key::AppSwitch, + TaoKey::Call => Key::Call, + TaoKey::Camera => Key::Camera, + TaoKey::CameraFocus => Key::CameraFocus, + TaoKey::EndCall => Key::EndCall, + TaoKey::GoBack => Key::GoBack, + TaoKey::GoHome => Key::GoHome, + TaoKey::HeadsetHook => Key::HeadsetHook, + TaoKey::LastNumberRedial => Key::LastNumberRedial, + TaoKey::Notification => Key::Notification, + TaoKey::MannerMode => Key::MannerMode, + TaoKey::VoiceDial => Key::VoiceDial, + TaoKey::TV => Key::TV, + TaoKey::TV3DMode => Key::TV3DMode, + TaoKey::TVAntennaCable => Key::TVAntennaCable, + TaoKey::TVAudioDescription => Key::TVAudioDescription, + TaoKey::TVAudioDescriptionMixDown => Key::TVAudioDescriptionMixDown, + TaoKey::TVAudioDescriptionMixUp => Key::TVAudioDescriptionMixUp, + TaoKey::TVContentsMenu => Key::TVContentsMenu, + TaoKey::TVDataService => Key::TVDataService, + TaoKey::TVInput => Key::TVInput, + TaoKey::TVInputComponent1 => Key::TVInputComponent1, + TaoKey::TVInputComponent2 => Key::TVInputComponent2, + TaoKey::TVInputComposite1 => Key::TVInputComposite1, + TaoKey::TVInputComposite2 => Key::TVInputComposite2, + TaoKey::TVInputHDMI1 => Key::TVInputHDMI1, + TaoKey::TVInputHDMI2 => Key::TVInputHDMI2, + TaoKey::TVInputHDMI3 => Key::TVInputHDMI3, + TaoKey::TVInputHDMI4 => Key::TVInputHDMI4, + TaoKey::TVInputVGA1 => Key::TVInputVGA1, + TaoKey::TVMediaContext => Key::TVMediaContext, + TaoKey::TVNetwork => Key::TVNetwork, + TaoKey::TVNumberEntry => Key::TVNumberEntry, + TaoKey::TVPower => Key::TVPower, + TaoKey::TVRadioService => Key::TVRadioService, + TaoKey::TVSatellite => Key::TVSatellite, + TaoKey::TVSatelliteBS => Key::TVSatelliteBS, + TaoKey::TVSatelliteCS => Key::TVSatelliteCS, + TaoKey::TVSatelliteToggle => Key::TVSatelliteToggle, + TaoKey::TVTerrestrialAnalog => Key::TVTerrestrialAnalog, + TaoKey::TVTerrestrialDigital => Key::TVTerrestrialDigital, + TaoKey::TVTimer => Key::TVTimer, + TaoKey::AVRInput => Key::AVRInput, + TaoKey::AVRPower => Key::AVRPower, + TaoKey::ColorF0Red => Key::ColorF0Red, + TaoKey::ColorF1Green => Key::ColorF1Green, + TaoKey::ColorF2Yellow => Key::ColorF2Yellow, + TaoKey::ColorF3Blue => Key::ColorF3Blue, + TaoKey::ColorF4Grey => Key::ColorF4Grey, + TaoKey::ColorF5Brown => Key::ColorF5Brown, + TaoKey::ClosedCaptionToggle => Key::ClosedCaptionToggle, + TaoKey::Dimmer => Key::Dimmer, + TaoKey::DisplaySwap => Key::DisplaySwap, + TaoKey::DVR => Key::DVR, + TaoKey::Exit => Key::Exit, + TaoKey::FavoriteClear0 => Key::FavoriteClear0, + TaoKey::FavoriteClear1 => Key::FavoriteClear1, + TaoKey::FavoriteClear2 => Key::FavoriteClear2, + TaoKey::FavoriteClear3 => Key::FavoriteClear3, + TaoKey::FavoriteRecall0 => Key::FavoriteRecall0, + TaoKey::FavoriteRecall1 => Key::FavoriteRecall1, + TaoKey::FavoriteRecall2 => Key::FavoriteRecall2, + TaoKey::FavoriteRecall3 => Key::FavoriteRecall3, + TaoKey::FavoriteStore0 => Key::FavoriteStore0, + TaoKey::FavoriteStore1 => Key::FavoriteStore1, + TaoKey::FavoriteStore2 => Key::FavoriteStore2, + TaoKey::FavoriteStore3 => Key::FavoriteStore3, + TaoKey::Guide => Key::Guide, + TaoKey::GuideNextDay => Key::GuideNextDay, + TaoKey::GuidePreviousDay => Key::GuidePreviousDay, + TaoKey::Info => Key::Info, + TaoKey::InstantReplay => Key::InstantReplay, + TaoKey::Link => Key::Link, + TaoKey::ListProgram => Key::ListProgram, + TaoKey::LiveContent => Key::LiveContent, + TaoKey::Lock => Key::Lock, + TaoKey::MediaApps => Key::MediaApps, + TaoKey::MediaAudioTrack => Key::MediaAudioTrack, + TaoKey::MediaLast => Key::MediaLast, + TaoKey::MediaSkipBackward => Key::MediaSkipBackward, + TaoKey::MediaSkipForward => Key::MediaSkipForward, + TaoKey::MediaStepBackward => Key::MediaStepBackward, + TaoKey::MediaStepForward => Key::MediaStepForward, + TaoKey::MediaTopMenu => Key::MediaTopMenu, + TaoKey::NavigateIn => Key::NavigateIn, + TaoKey::NavigateNext => Key::NavigateNext, + TaoKey::NavigateOut => Key::NavigateOut, + TaoKey::NavigatePrevious => Key::NavigatePrevious, + TaoKey::NextFavoriteChannel => Key::NextFavoriteChannel, + TaoKey::NextUserProfile => Key::NextUserProfile, + TaoKey::OnDemand => Key::OnDemand, + TaoKey::Pairing => Key::Pairing, + TaoKey::PinPDown => Key::PinPDown, + TaoKey::PinPMove => Key::PinPMove, + TaoKey::PinPToggle => Key::PinPToggle, + TaoKey::PinPUp => Key::PinPUp, + TaoKey::PlaySpeedDown => Key::PlaySpeedDown, + TaoKey::PlaySpeedReset => Key::PlaySpeedReset, + TaoKey::PlaySpeedUp => Key::PlaySpeedUp, + TaoKey::RandomToggle => Key::RandomToggle, + TaoKey::RcLowBattery => Key::RcLowBattery, + TaoKey::RecordSpeedNext => Key::RecordSpeedNext, + TaoKey::RfBypass => Key::RfBypass, + TaoKey::ScanChannelsToggle => Key::ScanChannelsToggle, + TaoKey::ScreenModeNext => Key::ScreenModeNext, + TaoKey::Settings => Key::Settings, + TaoKey::SplitScreenToggle => Key::SplitScreenToggle, + TaoKey::STBInput => Key::STBInput, + TaoKey::STBPower => Key::STBPower, + TaoKey::Subtitle => Key::Subtitle, + TaoKey::Teletext => Key::Teletext, + TaoKey::VideoModeNext => Key::VideoModeNext, + TaoKey::Wink => Key::Wink, + TaoKey::ZoomToggle => Key::ZoomToggle, + TaoKey::F1 => Key::F1, + TaoKey::F2 => Key::F2, + TaoKey::F3 => Key::F3, + TaoKey::F4 => Key::F4, + TaoKey::F5 => Key::F5, + TaoKey::F6 => Key::F6, + TaoKey::F7 => Key::F7, + TaoKey::F8 => Key::F8, + TaoKey::F9 => Key::F9, + TaoKey::F10 => Key::F10, + TaoKey::F11 => Key::F11, + TaoKey::F12 => Key::F12, + TaoKey::F13 => Key::F13, + TaoKey::F14 => Key::F14, + TaoKey::F15 => Key::F15, + TaoKey::F16 => Key::F16, + TaoKey::F17 => Key::F17, + TaoKey::F18 => Key::F18, + TaoKey::F19 => Key::F19, + TaoKey::F20 => Key::F20, + TaoKey::F21 => Key::F21, + TaoKey::F22 => Key::F22, + TaoKey::F23 => Key::F23, + TaoKey::F24 => Key::F24, + TaoKey::F25 => Key::F25, + TaoKey::F26 => Key::F26, + TaoKey::F27 => Key::F27, + TaoKey::F28 => Key::F28, + TaoKey::F29 => Key::F29, + TaoKey::F30 => Key::F30, + TaoKey::F31 => Key::F31, + TaoKey::F32 => Key::F32, + TaoKey::F33 => Key::F33, + TaoKey::F34 => Key::F34, + TaoKey::F35 => Key::F35, + _ => Key::Unidentified, + } +} + +fn convert_key_code(code: &TaoKeyCode) -> Code { + match code { + TaoKeyCode::Backquote => Code::Backquote, + TaoKeyCode::Backslash => Code::Backslash, + TaoKeyCode::BracketLeft => Code::BracketLeft, + TaoKeyCode::BracketRight => Code::BracketRight, + TaoKeyCode::Comma => Code::Comma, + TaoKeyCode::Digit0 => Code::Digit0, + TaoKeyCode::Digit1 => Code::Digit1, + TaoKeyCode::Digit2 => Code::Digit2, + TaoKeyCode::Digit3 => Code::Digit3, + TaoKeyCode::Digit4 => Code::Digit4, + TaoKeyCode::Digit5 => Code::Digit5, + TaoKeyCode::Digit6 => Code::Digit6, + TaoKeyCode::Digit7 => Code::Digit7, + TaoKeyCode::Digit8 => Code::Digit8, + TaoKeyCode::Digit9 => Code::Digit9, + TaoKeyCode::Equal => Code::Equal, + TaoKeyCode::IntlBackslash => Code::IntlBackslash, + TaoKeyCode::IntlRo => Code::IntlRo, + TaoKeyCode::IntlYen => Code::IntlYen, + TaoKeyCode::KeyA => Code::KeyA, + TaoKeyCode::KeyB => Code::KeyB, + TaoKeyCode::KeyC => Code::KeyC, + TaoKeyCode::KeyD => Code::KeyD, + TaoKeyCode::KeyE => Code::KeyE, + TaoKeyCode::KeyF => Code::KeyF, + TaoKeyCode::KeyG => Code::KeyG, + TaoKeyCode::KeyH => Code::KeyH, + TaoKeyCode::KeyI => Code::KeyI, + TaoKeyCode::KeyJ => Code::KeyJ, + TaoKeyCode::KeyK => Code::KeyK, + TaoKeyCode::KeyL => Code::KeyL, + TaoKeyCode::KeyM => Code::KeyM, + TaoKeyCode::KeyN => Code::KeyN, + TaoKeyCode::KeyO => Code::KeyO, + TaoKeyCode::KeyP => Code::KeyP, + TaoKeyCode::KeyQ => Code::KeyQ, + TaoKeyCode::KeyR => Code::KeyR, + TaoKeyCode::KeyS => Code::KeyS, + TaoKeyCode::KeyT => Code::KeyT, + TaoKeyCode::KeyU => Code::KeyU, + TaoKeyCode::KeyV => Code::KeyV, + TaoKeyCode::KeyW => Code::KeyW, + TaoKeyCode::KeyX => Code::KeyX, + TaoKeyCode::KeyY => Code::KeyY, + TaoKeyCode::KeyZ => Code::KeyZ, + TaoKeyCode::Minus => Code::Minus, + // The web at does not have Plus, + // but Equal means the key that represents =+ on the US keyboard. + TaoKeyCode::Plus => Code::Equal, + TaoKeyCode::Period => Code::Period, + TaoKeyCode::Quote => Code::Quote, + TaoKeyCode::Semicolon => Code::Semicolon, + TaoKeyCode::Slash => Code::Slash, + TaoKeyCode::AltLeft => Code::AltLeft, + TaoKeyCode::AltRight => Code::AltRight, + TaoKeyCode::Backspace => Code::Backspace, + TaoKeyCode::CapsLock => Code::CapsLock, + TaoKeyCode::ContextMenu => Code::ContextMenu, + TaoKeyCode::ControlLeft => Code::ControlLeft, + TaoKeyCode::ControlRight => Code::ControlRight, + TaoKeyCode::Enter => Code::Enter, + // What Tao calls super, the web at calls meta. + // It's the key that represents the Windows logo on Windows, and the Command key (⌘) on Mac. + TaoKeyCode::SuperLeft => Code::MetaLeft, + TaoKeyCode::SuperRight => Code::MetaRight, + TaoKeyCode::ShiftLeft => Code::ShiftLeft, + TaoKeyCode::ShiftRight => Code::ShiftRight, + TaoKeyCode::Space => Code::Space, + TaoKeyCode::Tab => Code::Tab, + TaoKeyCode::Convert => Code::Convert, + TaoKeyCode::KanaMode => Code::KanaMode, + TaoKeyCode::Lang1 => Code::Lang1, + TaoKeyCode::Lang2 => Code::Lang2, + TaoKeyCode::Lang3 => Code::Lang3, + TaoKeyCode::Lang4 => Code::Lang4, + TaoKeyCode::NonConvert => Code::NonConvert, + TaoKeyCode::Delete => Code::Delete, + TaoKeyCode::End => Code::End, + TaoKeyCode::Help => Code::Help, + TaoKeyCode::Home => Code::Home, + TaoKeyCode::Insert => Code::Insert, + TaoKeyCode::PageDown => Code::PageDown, + TaoKeyCode::PageUp => Code::PageUp, + TaoKeyCode::ArrowDown => Code::ArrowDown, + TaoKeyCode::ArrowLeft => Code::ArrowLeft, + TaoKeyCode::ArrowRight => Code::ArrowRight, + TaoKeyCode::ArrowUp => Code::ArrowUp, + TaoKeyCode::NumLock => Code::NumLock, + TaoKeyCode::Numpad0 => Code::Numpad0, + TaoKeyCode::Numpad1 => Code::Numpad1, + TaoKeyCode::Numpad2 => Code::Numpad2, + TaoKeyCode::Numpad3 => Code::Numpad3, + TaoKeyCode::Numpad4 => Code::Numpad4, + TaoKeyCode::Numpad5 => Code::Numpad5, + TaoKeyCode::Numpad6 => Code::Numpad6, + TaoKeyCode::Numpad7 => Code::Numpad7, + TaoKeyCode::Numpad8 => Code::Numpad8, + TaoKeyCode::Numpad9 => Code::Numpad9, + TaoKeyCode::NumpadAdd => Code::NumpadAdd, + TaoKeyCode::NumpadBackspace => Code::NumpadBackspace, + TaoKeyCode::NumpadClear => Code::NumpadClear, + TaoKeyCode::NumpadClearEntry => Code::NumpadClearEntry, + TaoKeyCode::NumpadComma => Code::NumpadComma, + TaoKeyCode::NumpadDecimal => Code::NumpadDecimal, + TaoKeyCode::NumpadDivide => Code::NumpadDivide, + TaoKeyCode::NumpadEnter => Code::NumpadEnter, + TaoKeyCode::NumpadEqual => Code::NumpadEqual, + TaoKeyCode::NumpadHash => Code::NumpadHash, + TaoKeyCode::NumpadMemoryAdd => Code::NumpadMemoryAdd, + TaoKeyCode::NumpadMemoryClear => Code::NumpadMemoryClear, + TaoKeyCode::NumpadMemoryRecall => Code::NumpadMemoryRecall, + TaoKeyCode::NumpadMemoryStore => Code::NumpadMemoryStore, + TaoKeyCode::NumpadMemorySubtract => Code::NumpadMemorySubtract, + TaoKeyCode::NumpadMultiply => Code::NumpadMultiply, + TaoKeyCode::NumpadParenLeft => Code::NumpadParenLeft, + TaoKeyCode::NumpadParenRight => Code::NumpadParenRight, + TaoKeyCode::NumpadStar => Code::NumpadStar, + TaoKeyCode::NumpadSubtract => Code::NumpadSubtract, + TaoKeyCode::Escape => Code::Escape, + TaoKeyCode::Fn => Code::Fn, + TaoKeyCode::FnLock => Code::FnLock, + TaoKeyCode::PrintScreen => Code::PrintScreen, + TaoKeyCode::ScrollLock => Code::ScrollLock, + TaoKeyCode::Pause => Code::Pause, + TaoKeyCode::BrowserBack => Code::BrowserBack, + TaoKeyCode::BrowserFavorites => Code::BrowserFavorites, + TaoKeyCode::BrowserForward => Code::BrowserForward, + TaoKeyCode::BrowserHome => Code::BrowserHome, + TaoKeyCode::BrowserRefresh => Code::BrowserRefresh, + TaoKeyCode::BrowserSearch => Code::BrowserSearch, + TaoKeyCode::BrowserStop => Code::BrowserStop, + TaoKeyCode::Eject => Code::Eject, + TaoKeyCode::LaunchApp1 => Code::LaunchApp1, + TaoKeyCode::LaunchApp2 => Code::LaunchApp2, + TaoKeyCode::LaunchMail => Code::LaunchMail, + TaoKeyCode::MediaPlayPause => Code::MediaPlayPause, + TaoKeyCode::MediaSelect => Code::MediaSelect, + TaoKeyCode::MediaStop => Code::MediaStop, + TaoKeyCode::MediaTrackNext => Code::MediaTrackNext, + TaoKeyCode::MediaTrackPrevious => Code::MediaTrackPrevious, + TaoKeyCode::Power => Code::Power, + TaoKeyCode::Sleep => Code::Sleep, + TaoKeyCode::AudioVolumeDown => Code::AudioVolumeDown, + TaoKeyCode::AudioVolumeMute => Code::AudioVolumeMute, + TaoKeyCode::AudioVolumeUp => Code::AudioVolumeUp, + TaoKeyCode::WakeUp => Code::WakeUp, + TaoKeyCode::Hyper => Code::Hyper, + TaoKeyCode::Turbo => Code::Turbo, + TaoKeyCode::Abort => Code::Abort, + TaoKeyCode::Resume => Code::Resume, + TaoKeyCode::Suspend => Code::Suspend, + TaoKeyCode::Again => Code::Again, + TaoKeyCode::Copy => Code::Copy, + TaoKeyCode::Cut => Code::Cut, + TaoKeyCode::Find => Code::Find, + TaoKeyCode::Open => Code::Open, + TaoKeyCode::Paste => Code::Paste, + TaoKeyCode::Props => Code::Props, + TaoKeyCode::Select => Code::Select, + TaoKeyCode::Undo => Code::Undo, + TaoKeyCode::Hiragana => Code::Hiragana, + TaoKeyCode::Katakana => Code::Katakana, + TaoKeyCode::F1 => Code::F1, + TaoKeyCode::F2 => Code::F2, + TaoKeyCode::F3 => Code::F3, + TaoKeyCode::F4 => Code::F4, + TaoKeyCode::F5 => Code::F5, + TaoKeyCode::F6 => Code::F6, + TaoKeyCode::F7 => Code::F7, + TaoKeyCode::F8 => Code::F8, + TaoKeyCode::F9 => Code::F9, + TaoKeyCode::F10 => Code::F10, + TaoKeyCode::F11 => Code::F11, + TaoKeyCode::F12 => Code::F12, + TaoKeyCode::F13 => Code::F13, + TaoKeyCode::F14 => Code::F14, + TaoKeyCode::F15 => Code::F15, + TaoKeyCode::F16 => Code::F16, + TaoKeyCode::F17 => Code::F17, + TaoKeyCode::F18 => Code::F18, + TaoKeyCode::F19 => Code::F19, + TaoKeyCode::F20 => Code::F20, + TaoKeyCode::F21 => Code::F21, + TaoKeyCode::F22 => Code::F22, + TaoKeyCode::F23 => Code::F23, + TaoKeyCode::F24 => Code::F24, + TaoKeyCode::F25 => Code::F25, + TaoKeyCode::F26 => Code::F26, + TaoKeyCode::F27 => Code::F27, + TaoKeyCode::F28 => Code::F28, + TaoKeyCode::F29 => Code::F29, + TaoKeyCode::F30 => Code::F30, + TaoKeyCode::F31 => Code::F31, + TaoKeyCode::F32 => Code::F32, + TaoKeyCode::F33 => Code::F33, + TaoKeyCode::F34 => Code::F34, + TaoKeyCode::F35 => Code::F35, + _ => Code::Unidentified, + } +} + +fn convert_key_state(state: &TaoElementState) -> Option { + match state { + TaoElementState::Pressed => Some(KeyState::Down), + TaoElementState::Released => Some(KeyState::Up), + _ => None, + } +} + +fn convert_location(location: &TaoKeyLocation) -> Option { + match location { + TaoKeyLocation::Standard => Some(Location::Standard), + TaoKeyLocation::Left => Some(Location::Left), + TaoKeyLocation::Right => Some(Location::Right), + TaoKeyLocation::Numpad => Some(Location::Numpad), + _ => None, + } +} diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index 7e8013d6a743..03a1c2ea88a4 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -125,6 +125,7 @@ use std::{ pub type WebviewId = u32; type IpcHandler = dyn Fn(Request) + 'static; +mod keyboard; #[cfg(any( windows, target_os = "linux", @@ -532,6 +533,11 @@ impl<'a> From<&TaoWindowEvent<'a>> for WindowEventWrapper { }, #[cfg(any(target_os = "linux", target_os = "macos"))] TaoWindowEvent::Focused(focused) => WindowEvent::Focused(*focused), + TaoWindowEvent::KeyboardInput { event, .. } => { + let event = keyboard::convert_key_event(event); + + WindowEvent::KeyboardInput { event } + } TaoWindowEvent::ThemeChanged(theme) => WindowEvent::ThemeChanged(map_theme(theme)), _ => return Self(None), }; diff --git a/crates/tauri-runtime/Cargo.toml b/crates/tauri-runtime/Cargo.toml index 0e2171b9c574..b8afec178368 100644 --- a/crates/tauri-runtime/Cargo.toml +++ b/crates/tauri-runtime/Cargo.toml @@ -34,6 +34,7 @@ http = "1" raw-window-handle = "0.6" url = { version = "2" } dpi = { version = "0.1", features = ["serde"] } +keyboard-types = "0.7.0" [target."cfg(windows)".dependencies.windows] version = "0.58" diff --git a/crates/tauri-runtime/src/keyboard.rs b/crates/tauri-runtime/src/keyboard.rs new file mode 100644 index 000000000000..b3abb1f45a48 --- /dev/null +++ b/crates/tauri-runtime/src/keyboard.rs @@ -0,0 +1,18 @@ +use serde::{Deserialize, Serialize}; + +pub use keyboard_types::{Code, Key, KeyState, Location, Modifiers}; + +/// Keyboard events are issued for all pressed and released keys. +#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct KeyboardEvent { + /// Whether the key is pressed or released. + pub state: KeyState, + /// Logical key value. + pub key: Key, + /// Physical key position. + pub code: Code, + /// Location for keys with multiple instances on common keyboards. + pub location: Location, + /// True if the key is currently auto-repeated. + pub repeat: bool, +} diff --git a/crates/tauri-runtime/src/lib.rs b/crates/tauri-runtime/src/lib.rs index 8c93a19a0907..bdd221536afc 100644 --- a/crates/tauri-runtime/src/lib.rs +++ b/crates/tauri-runtime/src/lib.rs @@ -21,6 +21,7 @@ use tauri_utils::Theme; use url::Url; use webview::{DetachedWebview, PendingWebview}; +pub mod keyboard; /// Types useful for interacting with a user's monitors. pub mod monitor; pub mod webview; diff --git a/crates/tauri-runtime/src/window.rs b/crates/tauri-runtime/src/window.rs index dc843100da98..c7ffed6b5f76 100644 --- a/crates/tauri-runtime/src/window.rs +++ b/crates/tauri-runtime/src/window.rs @@ -5,6 +5,7 @@ //! A layer between raw [`Runtime`] windows and Tauri. use crate::{ + keyboard::KeyboardEvent, webview::{DetachedWebview, PendingWebview}, Icon, Runtime, UserEvent, WindowDispatch, }; @@ -43,6 +44,10 @@ pub enum WindowEvent { /// /// The parameter is true if the window has gained focus, and false if it has lost focus. Focused(bool), + + /// An event from the keyboard has been received. + KeyboardInput { event: KeyboardEvent }, + /// The window's scale factor has changed. /// /// The following user actions can cause DPI changes: diff --git a/crates/tauri/src/app.rs b/crates/tauri/src/app.rs index 57fc7a00ac56..fb564a971762 100644 --- a/crates/tauri/src/app.rs +++ b/crates/tauri/src/app.rs @@ -33,6 +33,7 @@ use tauri_macros::default_runtime; use tauri_runtime::EventLoopProxy; use tauri_runtime::{ dpi::{PhysicalPosition, PhysicalSize}, + keyboard::KeyboardEvent, window::DragDropEvent, RuntimeInitArgs, }; @@ -115,6 +116,8 @@ pub enum WindowEvent { /// /// The parameter is true if the window has gained focus, and false if it has lost focus. Focused(bool), + /// An event from the keyboard has been received. + KeyboardInput(KeyboardEvent), /// The window's scale factor has changed. /// /// The following user actions can cause DPI changes: @@ -151,6 +154,7 @@ impl From for WindowEvent { }, RuntimeWindowEvent::Destroyed => Self::Destroyed, RuntimeWindowEvent::Focused(flag) => Self::Focused(flag), + RuntimeWindowEvent::KeyboardInput { event } => Self::KeyboardInput(event), RuntimeWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size, diff --git a/crates/tauri/src/manager/window.rs b/crates/tauri/src/manager/window.rs index f56f40a26c23..d3a828589ac9 100644 --- a/crates/tauri/src/manager/window.rs +++ b/crates/tauri/src/manager/window.rs @@ -28,6 +28,7 @@ const WINDOW_MOVED_EVENT: EventName<&str> = EventName::from_str("tauri://move"); const WINDOW_CLOSE_REQUESTED_EVENT: EventName<&str> = EventName::from_str("tauri://close-requested"); const WINDOW_DESTROYED_EVENT: EventName<&str> = EventName::from_str("tauri://destroyed"); +const WINDOW_KEYBOARD_INPUT_EVENT: EventName<&str> = EventName::from_str("tauri://keyboard-input"); const WINDOW_FOCUS_EVENT: EventName<&str> = EventName::from_str("tauri://focus"); const WINDOW_BLUR_EVENT: EventName<&str> = EventName::from_str("tauri://blur"); const WINDOW_SCALE_FACTOR_CHANGED_EVENT: EventName<&str> = @@ -180,6 +181,9 @@ fn on_window_event(window: &Window, event: &WindowEvent) -> crate }, &(), )?, + WindowEvent::KeyboardInput(event) => { + window.emit_to_window(WINDOW_KEYBOARD_INPUT_EVENT, event)?; + } WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size,