diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index d2547f731dcc5..07b2da041f0b9 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -278,7 +278,7 @@ impl App { /// /// # `run()` might not return /// - /// Calls to [`App::run()`] might never return. + /// Calls to [`App::run()`] will never return on iOS and Web. /// /// In simple and *headless* applications, one can expect that execution will /// proceed, normally, after calling [`run()`](App::run()) but this is not the case for @@ -289,10 +289,7 @@ impl App { /// window is closed and that event loop terminates – behavior of processes that /// do not is often platform dependent or undocumented. /// - /// By default, *Bevy* uses the `winit` crate for window creation. See - /// [`WinitSettings::return_from_run`](https://docs.rs/bevy/latest/bevy/winit/struct.WinitSettings.html#structfield.return_from_run) - /// for further discussion of this topic and for a mechanism to require that [`App::run()`] - /// *does* return – albeit one that carries its own caveats and disclaimers. + /// By default, *Bevy* uses the `winit` crate for window creation. /// /// # Panics /// diff --git a/crates/bevy_asset/src/io/android.rs b/crates/bevy_asset/src/io/android.rs index 3c5902e95592e..f792a72b00383 100644 --- a/crates/bevy_asset/src/io/android.rs +++ b/crates/bevy_asset/src/io/android.rs @@ -29,7 +29,7 @@ impl AssetReader for AndroidAssetReader { let mut opened_asset = asset_manager .open(&CString::new(path.to_str().unwrap()).unwrap()) .ok_or(AssetReaderError::NotFound(path.to_path_buf()))?; - let bytes = opened_asset.get_buffer()?; + let bytes = opened_asset.buffer()?; let reader: Box = Box::new(VecReader::new(bytes.to_vec())); Ok(reader) }) @@ -48,7 +48,7 @@ impl AssetReader for AndroidAssetReader { let mut opened_asset = asset_manager .open(&CString::new(meta_path.to_str().unwrap()).unwrap()) .ok_or(AssetReaderError::NotFound(meta_path))?; - let bytes = opened_asset.get_buffer()?; + let bytes = opened_asset.buffer()?; let reader: Box = Box::new(VecReader::new(bytes.to_vec())); Ok(reader) }) diff --git a/crates/bevy_input/src/keyboard.rs b/crates/bevy_input/src/keyboard.rs index 383a750a5e159..8b7b784db259c 100644 --- a/crates/bevy_input/src/keyboard.rs +++ b/crates/bevy_input/src/keyboard.rs @@ -1,5 +1,70 @@ //! The keyboard input functionality. +// This file contains a substantial portion of the UI Events Specification by the W3C. In +// particular, the variant names within `KeyCode` and their documentation are modified +// versions of contents of the aforementioned specification. +// +// The original documents are: +// +// +// ### For `KeyCode` +// UI Events KeyboardEvent code Values +// https://www.w3.org/TR/2017/CR-uievents-code-20170601/ +// Copyright © 2017 W3C® (MIT, ERCIM, Keio, Beihang). +// +// These documents were used under the terms of the following license. This W3C license as well as +// the W3C short notice apply to the `KeyCode` enums and their variants and the +// documentation attached to their variants. + +// --------- BEGGINING OF W3C LICENSE -------------------------------------------------------------- +// +// License +// +// By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, +// and will comply with the following terms and conditions. +// +// Permission to copy, modify, and distribute this work, with or without modification, for any +// purpose and without fee or royalty is hereby granted, provided that you include the following on +// ALL copies of the work or portions thereof, including modifications: +// +// - The full text of this NOTICE in a location viewable to users of the redistributed or derivative +// work. +// - Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none +// exist, the W3C Software and Document Short Notice should be included. +// - Notice of any changes or modifications, through a copyright statement on the new code or +// document such as "This software or document includes material copied from or derived from +// [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." +// +// Disclaimers +// +// THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR +// ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD +// PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. +// +// COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES +// ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. +// +// The name and trademarks of copyright holders may NOT be used in advertising or publicity +// pertaining to the work without specific, written prior permission. Title to copyright in this +// work will at all times remain with copyright holders. +// +// --------- END OF W3C LICENSE -------------------------------------------------------------------- + +// --------- BEGGINING OF W3C SHORT NOTICE --------------------------------------------------------- +// +// winit: https://github.com/rust-windowing/winit +// +// Copyright © 2021 World Wide Web Consortium, (Massachusetts Institute of Technology, European +// Research Consortium for Informatics and Mathematics, Keio University, Beihang). All Rights +// Reserved. This work is distributed under the W3C® Software License [1] in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// [1] http://www.w3.org/Consortium/Legal/copyright-software +// +// --------- END OF W3C SHORT NOTICE --------------------------------------------------------------- + use crate::{ButtonInput, ButtonState}; use bevy_ecs::entity::Entity; use bevy_ecs::{ @@ -29,10 +94,8 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; reflect(Serialize, Deserialize) )] pub struct KeyboardInput { - /// The scan code of the key. - pub scan_code: u32, /// The key code of the key. - pub key_code: Option, + pub key_code: KeyCode, /// The press state of the key. pub state: ButtonState, /// Window that received the input. @@ -43,39 +106,69 @@ pub struct KeyboardInput { /// /// ## Differences /// -/// The main difference between the [`KeyboardInput`] event and the [`ButtonInput`] or [`ButtonInput`] resources is that +/// The main difference between the [`KeyboardInput`] event and the [`ButtonInput`] resources is that /// the latter have convenient functions such as [`ButtonInput::pressed`], [`ButtonInput::just_pressed`] and [`ButtonInput::just_released`]. pub fn keyboard_input_system( - mut scan_input: ResMut>, mut key_input: ResMut>, mut keyboard_input_events: EventReader, ) { // Avoid clearing if it's not empty to ensure change detection is not triggered. - scan_input.bypass_change_detection().clear(); key_input.bypass_change_detection().clear(); for event in keyboard_input_events.read() { let KeyboardInput { - scan_code, state, .. + key_code, state, .. } = event; - if let Some(key_code) = event.key_code { - match state { - ButtonState::Pressed => key_input.press(key_code), - ButtonState::Released => key_input.release(key_code), - } - } match state { - ButtonState::Pressed => scan_input.press(ScanCode(*scan_code)), - ButtonState::Released => scan_input.release(ScanCode(*scan_code)), + ButtonState::Pressed => key_input.press(*key_code), + ButtonState::Released => key_input.release(*key_code), } } } +/// Contains the platform-native physical key identifier +/// +/// The exact values vary from platform to platform (which is part of why this is a per-platform +/// enum), but the values are primarily tied to the key's physical location on the keyboard. +/// +/// This enum is primarily used to store raw keycodes when Winit doesn't map a given native +/// physical key identifier to a meaningful [`KeyCode`] variant. In the presence of identifiers we +/// haven't mapped for you yet, this lets you use use [`KeyCode`] to: +/// +/// - Correctly match key press and release events. +/// - On non-web platforms, support assigning keybinds to virtually any key through a UI. +#[derive(Debug, Clone, Ord, PartialOrd, Copy, PartialEq, Eq, Hash, Reflect)] +#[cfg_attr( + feature = "serialize", + derive(serde::Serialize, serde::Deserialize), + reflect(Serialize, Deserialize) +)] +pub enum NativeKeyCode { + /// Unidentified + Unidentified, + /// An Android "scancode". + Android(u32), + /// A macOS "scancode". + MacOS(u16), + /// A Windows "scancode". + Windows(u16), + /// An XKB "keycode". + Xkb(u32), +} + /// The key code of a [`KeyboardInput`]. /// /// ## Usage /// /// It is used as the generic `T` value of an [`ButtonInput`] to create a `Res>`. -/// The resource values are mapped to the current layout of the keyboard and correlate to an [`ScanCode`]. +/// +/// Code representing the location of a physical key +/// This mostly conforms to the UI Events Specification's [`KeyboardEvent.code`] with a few +/// exceptions: +/// - The keys that the specification calls `MetaLeft` and `MetaRight` are named `SuperLeft` and +/// `SuperRight` here. +/// - The key that the specification calls "Super" is reported as `Unidentified` here. +/// +/// [`KeyboardEvent.code`]: https://w3c.github.io/uievents-code/#code-value-tables /// /// ## Updating /// @@ -89,375 +182,471 @@ pub fn keyboard_input_system( )] #[repr(u32)] pub enum KeyCode { - /// The `1` key over the letters. - Key1, - /// The `2` key over the letters. - Key2, - /// The `3` key over the letters. - Key3, - /// The `4` key over the letters. - Key4, - /// The `5` key over the letters. - Key5, - /// The `6` key over the letters. - Key6, - /// The `7` key over the letters. - Key7, - /// The `8` key over the letters. - Key8, - /// The `9` key over the letters. - Key9, - /// The `0` key over the letters. - Key0, - - /// The `A` key. - A, - /// The `B` key. - B, - /// The `C` key. - C, - /// The `D` key. - D, - /// The `E` key. - E, - /// The `F` key. - F, - /// The `G` key. - G, - /// The `H` key. - H, - /// The `I` key. - I, - /// The `J` key. - J, - /// The `K` key. - K, - /// The `L` key. - L, - /// The `M` key. - M, - /// The `N` key. - N, - /// The `O` key. - O, - /// The `P` key. - P, - /// The `Q` key. - Q, - /// The `R` key. - R, - /// The `S` key. - S, - /// The `T` key. - T, - /// The `U` key. - U, - /// The `V` key. - V, - /// The `W` key. - W, - /// The `X` key. - X, - /// The `Y` key. - Y, - /// The `Z` key. - Z, - - /// The `Escape` / `ESC` key, next to the `F1` key. + /// This variant is used when the key cannot be translated to any other variant. + /// + /// The native keycode is provided (if available) so you're able to more reliably match + /// key-press and key-release events by hashing the [`KeyCode`]. It is also possible to use + /// this for keybinds for non-standard keys, but such keybinds are tied to a given platform. + Unidentified(NativeKeyCode), + /// ` on a US keyboard. This is also called a backtick or grave. + /// This is the 半角/全角/漢字 + /// (hankaku/zenkaku/kanji) key on Japanese keyboards + Backquote, + /// Used for both the US \\ (on the 101-key layout) and also for the key + /// located between the " and Enter keys on row C of the 102-, + /// 104- and 106-key layouts. + /// Labeled # on a UK (102) keyboard. + Backslash, + /// [ on a US keyboard. + BracketLeft, + /// ] on a US keyboard. + BracketRight, + /// , on a US keyboard. + Comma, + /// 0 on a US keyboard. + Digit0, + /// 1 on a US keyboard. + Digit1, + /// 2 on a US keyboard. + Digit2, + /// 3 on a US keyboard. + Digit3, + /// 4 on a US keyboard. + Digit4, + /// 5 on a US keyboard. + Digit5, + /// 6 on a US keyboard. + Digit6, + /// 7 on a US keyboard. + Digit7, + /// 8 on a US keyboard. + Digit8, + /// 9 on a US keyboard. + Digit9, + /// = on a US keyboard. + Equal, + /// Located between the left Shift and Z keys. + /// Labeled \\ on a UK keyboard. + IntlBackslash, + /// Located between the / and right Shift keys. + /// Labeled \\ (ro) on a Japanese keyboard. + IntlRo, + /// Located between the = and Backspace keys. + /// Labeled ¥ (yen) on a Japanese keyboard. \\ on a + /// Russian keyboard. + IntlYen, + /// a on a US keyboard. + /// Labeled q on an AZERTY (e.g., French) keyboard. + KeyA, + /// b on a US keyboard. + KeyB, + /// c on a US keyboard. + KeyC, + /// d on a US keyboard. + KeyD, + /// e on a US keyboard. + KeyE, + /// f on a US keyboard. + KeyF, + /// g on a US keyboard. + KeyG, + /// h on a US keyboard. + KeyH, + /// i on a US keyboard. + KeyI, + /// j on a US keyboard. + KeyJ, + /// k on a US keyboard. + KeyK, + /// l on a US keyboard. + KeyL, + /// m on a US keyboard. + KeyM, + /// n on a US keyboard. + KeyN, + /// o on a US keyboard. + KeyO, + /// p on a US keyboard. + KeyP, + /// q on a US keyboard. + /// Labeled a on an AZERTY (e.g., French) keyboard. + KeyQ, + /// r on a US keyboard. + KeyR, + /// s on a US keyboard. + KeyS, + /// t on a US keyboard. + KeyT, + /// u on a US keyboard. + KeyU, + /// v on a US keyboard. + KeyV, + /// w on a US keyboard. + /// Labeled z on an AZERTY (e.g., French) keyboard. + KeyW, + /// x on a US keyboard. + KeyX, + /// y on a US keyboard. + /// Labeled z on a QWERTZ (e.g., German) keyboard. + KeyY, + /// z on a US keyboard. + /// Labeled w on an AZERTY (e.g., French) keyboard, and y on a + /// QWERTZ (e.g., German) keyboard. + KeyZ, + /// - on a US keyboard. + Minus, + /// . on a US keyboard. + Period, + /// ' on a US keyboard. + Quote, + /// ; on a US keyboard. + Semicolon, + /// / on a US keyboard. + Slash, + /// Alt, Option, or . + AltLeft, + /// Alt, Option, or . + /// This is labeled AltGr on many keyboard layouts. + AltRight, + /// Backspace or . + /// Labeled Delete on Apple keyboards. + Backspace, + /// CapsLock or + CapsLock, + /// The application context menu key, which is typically found between the right + /// Super key and the right Control key. + ContextMenu, + /// Control or + ControlLeft, + /// Control or + ControlRight, + /// Enter or . Labeled Return on Apple keyboards. + Enter, + /// The Windows, , Command, or other OS symbol key. + SuperLeft, + /// The Windows, , Command, or other OS symbol key. + SuperRight, + /// Shift or + ShiftLeft, + /// Shift or + ShiftRight, + ///   (space) + Space, + /// Tab or + Tab, + /// Japanese: (henkan) + Convert, + /// Japanese: カタカナ/ひらがな/ローマ字 (katakana/hiragana/romaji) + KanaMode, + /// Korean: HangulMode 한/영 (han/yeong) + /// + /// Japanese (Mac keyboard): (kana) + Lang1, + /// Korean: Hanja (hanja) + /// + /// Japanese (Mac keyboard): (eisu) + Lang2, + /// Japanese (word-processing keyboard): Katakana + Lang3, + /// Japanese (word-processing keyboard): Hiragana + Lang4, + /// Japanese (word-processing keyboard): Zenkaku/Hankaku + Lang5, + /// Japanese: 無変換 (muhenkan) + NonConvert, + /// . The forward delete key. + /// Note that on Apple keyboards, the key labelled Delete on the main part of + /// the keyboard is encoded as [`Backspace`]. + /// + /// [`Backspace`]: Self::Backspace + Delete, + /// Page Down, End, or + End, + /// Help. Not present on standard PC keyboards. + Help, + /// Home or + Home, + /// Insert or Ins. Not present on Apple keyboards. + Insert, + /// Page Down, PgDn, or + PageDown, + /// Page Up, PgUp, or + PageUp, + /// + ArrowDown, + /// + ArrowLeft, + /// + ArrowRight, + /// + ArrowUp, + /// On the Mac, this is used for the numpad Clear key. + NumLock, + /// 0 Ins on a keyboard. 0 on a phone or remote control + Numpad0, + /// 1 End on a keyboard. 1 or 1 QZ on a phone or remote control + Numpad1, + /// 2 ↓ on a keyboard. 2 ABC on a phone or remote control + Numpad2, + /// 3 PgDn on a keyboard. 3 DEF on a phone or remote control + Numpad3, + /// 4 ← on a keyboard. 4 GHI on a phone or remote control + Numpad4, + /// 5 on a keyboard. 5 JKL on a phone or remote control + Numpad5, + /// 6 → on a keyboard. 6 MNO on a phone or remote control + Numpad6, + /// 7 Home on a keyboard. 7 PQRS or 7 PRS on a phone + /// or remote control + Numpad7, + /// 8 ↑ on a keyboard. 8 TUV on a phone or remote control + Numpad8, + /// 9 PgUp on a keyboard. 9 WXYZ or 9 WXY on a phone + /// or remote control + Numpad9, + /// + + NumpadAdd, + /// Found on the Microsoft Natural Keyboard. + NumpadBackspace, + /// C or A (All Clear). Also for use with numpads that have a + /// Clear key that is separate from the NumLock key. On the Mac, the + /// numpad Clear key is encoded as [`NumLock`]. + /// + /// [`NumLock`]: Self::NumLock + NumpadClear, + /// C (Clear Entry) + NumpadClearEntry, + /// , (thousands separator). For locales where the thousands separator + /// is a "." (e.g., Brazil), this key may generate a .. + NumpadComma, + /// . Del. For locales where the decimal separator is "," (e.g., + /// Brazil), this key may generate a ,. + NumpadDecimal, + /// / + NumpadDivide, + /// The Enter key on the numpad. + NumpadEnter, + /// = + NumpadEqual, + /// # on a phone or remote control device. This key is typically found + /// below the 9 key and to the right of the 0 key. + NumpadHash, + /// M Add current entry to the value stored in memory. + NumpadMemoryAdd, + /// M Clear the value stored in memory. + NumpadMemoryClear, + /// M Replace the current entry with the value stored in memory. + NumpadMemoryRecall, + /// M Replace the value stored in memory with the current entry. + NumpadMemoryStore, + /// M Subtract current entry from the value stored in memory. + NumpadMemorySubtract, + /// * on a keyboard. For use with numpads that provide mathematical + /// operations (+, - * and /). + /// + /// Use `NumpadStar` for the * key on phones and remote controls. + NumpadMultiply, + /// ( Found on the Microsoft Natural Keyboard. + NumpadParenLeft, + /// ) Found on the Microsoft Natural Keyboard. + NumpadParenRight, + /// * on a phone or remote control device. + /// + /// This key is typically found below the 7 key and to the left of + /// the 0 key. + /// + /// Use "NumpadMultiply" for the * key on + /// numeric keypads. + NumpadStar, + /// - + NumpadSubtract, + /// Esc or Escape, - - /// The `F1` key. + /// Fn This is typically a hardware key that does not generate a separate code. + Fn, + /// FLock or FnLock. Function Lock key. Found on the Microsoft + /// Natural Keyboard. + FnLock, + /// PrtScr SysRq or Print Screen + PrintScreen, + /// Scroll Lock + ScrollLock, + /// Pause Break + Pause, + /// Some laptops place this key to the left of the key. + /// + /// This also the "back" button (triangle) on Android. + BrowserBack, + /// BrowserFavorites + BrowserFavorites, + /// Some laptops place this key to the right of the key. + BrowserForward, + /// The "home" button on Android. + BrowserHome, + /// BrowserRefresh + BrowserRefresh, + /// BrowserSearch + BrowserSearch, + /// BrowserStop + BrowserStop, + /// Eject or . This key is placed in the function section on some Apple + /// keyboards. + Eject, + /// Sometimes labelled My Computer on the keyboard + LaunchApp1, + /// Sometimes labelled Calculator on the keyboard + LaunchApp2, + /// LaunchMail + LaunchMail, + /// MediaPlayPause + MediaPlayPause, + /// MediaSelect + MediaSelect, + /// MediaStop + MediaStop, + /// MediaTrackNext + MediaTrackNext, + /// MediaTrackPrevious + MediaTrackPrevious, + /// This key is placed in the function section on some Apple keyboards, replacing the + /// Eject key. + Power, + /// Sleep + Sleep, + /// AudioVolumeDown + AudioVolumeDown, + /// AudioVolumeMute + AudioVolumeMute, + /// AudioVolumeUp + AudioVolumeUp, + /// WakeUp + WakeUp, + /// Legacy modifier key. Also called "Super" in certain places. + Meta, + /// Legacy modifier key. + Hyper, + /// Turbo + Turbo, + /// Abort + Abort, + /// Resume + Resume, + /// Suspend + Suspend, + /// Found on Sun’s USB keyboard. + Again, + /// Found on Sun’s USB keyboard. + Copy, + /// Found on Sun’s USB keyboard. + Cut, + /// Found on Sun’s USB keyboard. + Find, + /// Found on Sun’s USB keyboard. + Open, + /// Found on Sun’s USB keyboard. + Paste, + /// Found on Sun’s USB keyboard. + Props, + /// Found on Sun’s USB keyboard. + Select, + /// Found on Sun’s USB keyboard. + Undo, + /// Use for dedicated ひらがな key found on some Japanese word processing keyboards. + Hiragana, + /// Use for dedicated カタカナ key found on some Japanese word processing keyboards. + Katakana, + /// General-purpose function key. + /// Usually found at the top of the keyboard. F1, - /// The `F2` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F2, - /// The `F3` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F3, - /// The `F4` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F4, - /// The `F5` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F5, - /// The `F6` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F6, - /// The `F7` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F7, - /// The `F8` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F8, - /// The `F9` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F9, - /// The `F10` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F10, - /// The `F11` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F11, - /// The `F12` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F12, - /// The `F13` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F13, - /// The `F14` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F14, - /// The `F15` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F15, - /// The `F16` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F16, - /// The `F17` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F17, - /// The `F18` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F18, - /// The `F19` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F19, - /// The `F20` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F20, - /// The `F21` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F21, - /// The `F22` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F22, - /// The `F23` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F23, - /// The `F24` key. + /// General-purpose function key. + /// Usually found at the top of the keyboard. F24, - - /// The `Snapshot` / `Print Screen` key. - Snapshot, - /// The `Scroll` / `Scroll Lock` key. - Scroll, - /// The `Pause` / `Break` key, next to the `Scroll` key. - Pause, - - /// The `Insert` key, next to the `Backspace` key. - Insert, - /// The `Home` key. - Home, - /// The `Delete` key. - Delete, - /// The `End` key. - End, - /// The `PageDown` key. - PageDown, - /// The `PageUp` key. - PageUp, - - /// The `Left` / `Left Arrow` key. - Left, - /// The `Up` / `Up Arrow` key. - Up, - /// The `Right` / `Right Arrow` key. - Right, - /// The `Down` / `Down Arrow` key. - Down, - - /// The `Back` / `Backspace` key. - Back, - /// The `Return` / `Enter` key. - Return, - /// The `Space` / `Spacebar` / ` ` key. - Space, - - /// The `Compose` key on Linux. - Compose, - /// The `Caret` / `^` key. - Caret, - - /// The `Numlock` key. - Numlock, - /// The `Numpad0` / `0` key. - Numpad0, - /// The `Numpad1` / `1` key. - Numpad1, - /// The `Numpad2` / `2` key. - Numpad2, - /// The `Numpad3` / `3` key. - Numpad3, - /// The `Numpad4` / `4` key. - Numpad4, - /// The `Numpad5` / `5` key. - Numpad5, - /// The `Numpad6` / `6` key. - Numpad6, - /// The `Numpad7` / `7` key. - Numpad7, - /// The `Numpad8` / `8` key. - Numpad8, - /// The `Numpad9` / `9` key. - Numpad9, - - /// The `AbntC1` key. - AbntC1, - /// The `AbntC2` key. - AbntC2, - - /// The `NumpadAdd` / `+` key. - NumpadAdd, - /// The `Apostrophe` / `'` key. - Apostrophe, - /// The `Apps` key. - Apps, - /// The `Asterisk` / `*` key. - Asterisk, - /// The `Plus` / `+` key. - Plus, - /// The `At` / `@` key. - At, - /// The `Ax` key. - Ax, - /// The `Backslash` / `\` key. - Backslash, - /// The `Calculator` key. - Calculator, - /// The `Capital` key. - Capital, - /// The `Colon` / `:` key. - Colon, - /// The `Comma` / `,` key. - Comma, - /// The `Convert` key. - Convert, - /// The `NumpadDecimal` / `.` key. - NumpadDecimal, - /// The `NumpadDivide` / `/` key. - NumpadDivide, - /// The `Equals` / `=` key. - Equals, - /// The `Grave` / `Backtick` / `` ` `` key. - Grave, - /// The `Kana` key. - Kana, - /// The `Kanji` key. - Kanji, - - /// The `Left Alt` key. Maps to `Left Option` on Mac. - AltLeft, - /// The `Left Bracket` / `[` key. - BracketLeft, - /// The `Left Control` key. - ControlLeft, - /// The `Left Shift` key. - ShiftLeft, - /// The `Left Super` key. - /// Generic keyboards usually display this key with the *Microsoft Windows* logo. - /// Apple keyboards call this key the *Command Key* and display it using the ⌘ character. - #[doc(alias("LWin", "LMeta", "LLogo"))] - SuperLeft, - - /// The `Mail` key. - Mail, - /// The `MediaSelect` key. - MediaSelect, - /// The `MediaStop` key. - MediaStop, - /// The `Minus` / `-` key. - Minus, - /// The `NumpadMultiply` / `*` key. - NumpadMultiply, - /// The `Mute` key. - Mute, - /// The `MyComputer` key. - MyComputer, - /// The `NavigateForward` / `Prior` key. - NavigateForward, - /// The `NavigateBackward` / `Next` key. - NavigateBackward, - /// The `NextTrack` key. - NextTrack, - /// The `NoConvert` key. - NoConvert, - /// The `NumpadComma` / `,` key. - NumpadComma, - /// The `NumpadEnter` key. - NumpadEnter, - /// The `NumpadEquals` / `=` key. - NumpadEquals, - /// The `Oem102` key. - Oem102, - /// The `Period` / `.` key. - Period, - /// The `PlayPause` key. - PlayPause, - /// The `Power` key. - Power, - /// The `PrevTrack` key. - PrevTrack, - - /// The `Right Alt` key. Maps to `Right Option` on Mac. - AltRight, - /// The `Right Bracket` / `]` key. - BracketRight, - /// The `Right Control` key. - ControlRight, - /// The `Right Shift` key. - ShiftRight, - /// The `Right Super` key. - /// Generic keyboards usually display this key with the *Microsoft Windows* logo. - /// Apple keyboards call this key the *Command Key* and display it using the ⌘ character. - #[doc(alias("RWin", "RMeta", "RLogo"))] - SuperRight, - - /// The `Semicolon` / `;` key. - Semicolon, - /// The `Slash` / `/` key. - Slash, - /// The `Sleep` key. - Sleep, - /// The `Stop` key. - Stop, - /// The `NumpadSubtract` / `-` key. - NumpadSubtract, - /// The `Sysrq` key. - Sysrq, - /// The `Tab` / ` ` key. - Tab, - /// The `Underline` / `_` key. - Underline, - /// The `Unlabeled` key. - Unlabeled, - - /// The `VolumeDown` key. - VolumeDown, - /// The `VolumeUp` key. - VolumeUp, - - /// The `Wake` key. - Wake, - - /// The `WebBack` key. - WebBack, - /// The `WebFavorites` key. - WebFavorites, - /// The `WebForward` key. - WebForward, - /// The `WebHome` key. - WebHome, - /// The `WebRefresh` key. - WebRefresh, - /// The `WebSearch` key. - WebSearch, - /// The `WebStop` key. - WebStop, - - /// The `Yen` key. - Yen, - - /// The `Copy` key. - Copy, - /// The `Paste` key. - Paste, - /// The `Cut` key. - Cut, + /// General-purpose function key. + F25, + /// General-purpose function key. + F26, + /// General-purpose function key. + F27, + /// General-purpose function key. + F28, + /// General-purpose function key. + F29, + /// General-purpose function key. + F30, + /// General-purpose function key. + F31, + /// General-purpose function key. + F32, + /// General-purpose function key. + F33, + /// General-purpose function key. + F34, + /// General-purpose function key. + F35, } - -/// The scan code of a [`KeyboardInput`]. -/// -/// ## Usage -/// -/// It is used as the generic `` value of an [`ButtonInput`] to create a `Res>`. -/// The resource values are mapped to the physical location of a key on the keyboard and correlate to an [`KeyCode`] -/// -/// ## Updating -/// -/// The resource is updated inside of the [`keyboard_input_system`]. -#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Reflect)] -#[reflect(Debug, Hash, PartialEq)] -#[cfg_attr( - feature = "serialize", - derive(serde::Serialize, serde::Deserialize), - reflect(Serialize, Deserialize) -)] -pub struct ScanCode(pub u32); diff --git a/crates/bevy_input/src/lib.rs b/crates/bevy_input/src/lib.rs index ae22786f30656..c3f2b3af9e4f2 100644 --- a/crates/bevy_input/src/lib.rs +++ b/crates/bevy_input/src/lib.rs @@ -26,7 +26,7 @@ pub mod prelude { gamepad::{ Gamepad, GamepadAxis, GamepadAxisType, GamepadButton, GamepadButtonType, Gamepads, }, - keyboard::{KeyCode, ScanCode}, + keyboard::KeyCode, mouse::MouseButton, touch::{TouchInput, Touches}, Axis, ButtonInput, @@ -36,7 +36,7 @@ pub mod prelude { use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_reflect::Reflect; -use keyboard::{keyboard_input_system, KeyCode, KeyboardInput, ScanCode}; +use keyboard::{keyboard_input_system, KeyCode, KeyboardInput}; use mouse::{ mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel, @@ -69,7 +69,6 @@ impl Plugin for InputPlugin { // keyboard .add_event::() .init_resource::>() - .init_resource::>() .add_systems(PreUpdate, keyboard_input_system.in_set(InputSystem)) // mouse .add_event::() @@ -115,8 +114,7 @@ impl Plugin for InputPlugin { // Register keyboard types app.register_type::() - .register_type::() - .register_type::(); + .register_type::(); // Register mouse types app.register_type::() diff --git a/crates/bevy_input/src/mouse.rs b/crates/bevy_input/src/mouse.rs index 7c90ff1fcb2c6..4eb34c6187032 100644 --- a/crates/bevy_input/src/mouse.rs +++ b/crates/bevy_input/src/mouse.rs @@ -61,6 +61,10 @@ pub enum MouseButton { Right, /// The middle mouse button. Middle, + /// The back mouse button. + Back, + /// The forward mouse button. + Forward, /// Another mouse button with the associated number. Other(u16), } diff --git a/crates/bevy_tasks/Cargo.toml b/crates/bevy_tasks/Cargo.toml index fb36d711f3d9a..f374d7f8a9134 100644 --- a/crates/bevy_tasks/Cargo.toml +++ b/crates/bevy_tasks/Cargo.toml @@ -23,7 +23,7 @@ concurrent-queue = "2.0.0" wasm-bindgen-futures = "0.4" [dev-dependencies] -instant = { version = "0.1", features = ["wasm-bindgen"] } +web-time = { version = "0.2" } [lints] workspace = true diff --git a/crates/bevy_tasks/examples/busy_behavior.rs b/crates/bevy_tasks/examples/busy_behavior.rs index 8a74034e0ca90..23a43de017a59 100644 --- a/crates/bevy_tasks/examples/busy_behavior.rs +++ b/crates/bevy_tasks/examples/busy_behavior.rs @@ -1,4 +1,5 @@ use bevy_tasks::TaskPoolBuilder; +use web_time::{Duration, Instant}; // This sample demonstrates creating a thread pool with 4 tasks and spawning 40 tasks that spin // for 100ms. It's expected to take about a second to run (assuming the machine has >= 4 logical @@ -10,12 +11,12 @@ fn main() { .num_threads(4) .build(); - let t0 = instant::Instant::now(); + let t0 = Instant::now(); pool.scope(|s| { for i in 0..40 { s.spawn(async move { - let now = instant::Instant::now(); - while instant::Instant::now() - now < instant::Duration::from_millis(100) { + let now = Instant::now(); + while Instant::now() - now < Duration::from_millis(100) { // spin, simulating work being done } @@ -28,6 +29,6 @@ fn main() { } }); - let t1 = instant::Instant::now(); + let t1 = Instant::now(); println!("all tasks finished in {} secs", (t1 - t0).as_secs_f32()); } diff --git a/crates/bevy_tasks/examples/idle_behavior.rs b/crates/bevy_tasks/examples/idle_behavior.rs index daa2eaf2e2a89..3ce121f989fc3 100644 --- a/crates/bevy_tasks/examples/idle_behavior.rs +++ b/crates/bevy_tasks/examples/idle_behavior.rs @@ -1,4 +1,5 @@ use bevy_tasks::TaskPoolBuilder; +use web_time::{Duration, Instant}; // This sample demonstrates a thread pool with one thread per logical core and only one task // spinning. Other than the one thread, the system should remain idle, demonstrating good behavior @@ -13,8 +14,8 @@ fn main() { for i in 0..1 { s.spawn(async move { println!("Blocking for 10 seconds"); - let now = instant::Instant::now(); - while instant::Instant::now() - now < instant::Duration::from_millis(10000) { + let now = Instant::now(); + while Instant::now() - now < Duration::from_millis(10000) { // spin, simulating work being done } diff --git a/crates/bevy_time/src/real.rs b/crates/bevy_time/src/real.rs index b1922b635bca9..90b7b8042df23 100644 --- a/crates/bevy_time/src/real.rs +++ b/crates/bevy_time/src/real.rs @@ -25,7 +25,7 @@ use crate::time::Time; /// zero must be handled without errors in application logic, as it may /// theoretically also happen at other times. /// -/// [`Instant`](std::time::Instant)s for [`startup()`](Time::startup), +/// [`Instant`]s for [`startup()`](Time::startup), /// [`first_update()`](Time::first_update) and /// [`last_update()`](Time::last_update) are recorded and accessible. #[derive(Debug, Copy, Clone, Reflect)] @@ -47,7 +47,7 @@ impl Default for Real { impl Time { /// Constructs a new `Time` instance with a specific startup - /// [`Instant`](std::time::Instant). + /// [`Instant`]. pub fn new(startup: Instant) -> Self { Self::new_with(Real { startup, @@ -77,7 +77,7 @@ impl Time { self.update_with_instant(last_update + duration); } - /// Updates time with a specified [`Instant`](std::time::Instant). + /// Updates time with a specified [`Instant`]. /// /// This method is provided for use in tests. /// @@ -95,7 +95,7 @@ impl Time { self.context_mut().last_update = Some(instant); } - /// Returns the [`Instant`](std::time::Instant) the clock was created. + /// Returns the [`Instant`] the clock was created. /// /// This usually represents when the app was started. #[inline] @@ -103,7 +103,7 @@ impl Time { self.context().startup } - /// Returns the [`Instant`](std::time::Instant) when [`Self::update`] was first called, if it + /// Returns the [`Instant`] when [`Self::update`] was first called, if it /// exists. /// /// This usually represents when the first app update started. @@ -112,7 +112,7 @@ impl Time { self.context().first_update } - /// Returns the [`Instant`](std::time::Instant) when [`Self::update`] was last called, if it + /// Returns the [`Instant`] when [`Self::update`] was last called, if it /// exists. /// /// This usually represents when the current app update started. diff --git a/crates/bevy_utils/Cargo.toml b/crates/bevy_utils/Cargo.toml index bf1eea4b5f069..be3d039da1b10 100644 --- a/crates/bevy_utils/Cargo.toml +++ b/crates/bevy_utils/Cargo.toml @@ -14,7 +14,7 @@ detailed_trace = [] [dependencies] ahash = "0.8.3" tracing = { version = "0.1", default-features = false, features = ["std"] } -instant = { version = "0.1", features = ["wasm-bindgen"] } +web-time = { version = "0.2" } uuid = { version = "1.1", features = ["v4", "serde"] } hashbrown = { version = "0.14", features = ["serde"] } bevy_utils_proc_macros = { version = "0.12.0", path = "macros" } diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index ec7344e3b114a..78e3a449a249e 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -31,10 +31,10 @@ pub use cow_arc::*; pub use default::default; pub use float_ord::*; pub use hashbrown; -pub use instant::{Duration, Instant, SystemTime}; pub use petgraph; pub use thiserror; pub use tracing; +pub use web_time::{Duration, Instant}; #[allow(missing_docs)] pub mod nonmax { diff --git a/crates/bevy_window/Cargo.toml b/crates/bevy_window/Cargo.toml index a0561c8e83a1c..b67cdef0b0d8d 100644 --- a/crates/bevy_window/Cargo.toml +++ b/crates/bevy_window/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["bevy"] [features] default = [] -serialize = ["serde"] +serialize = ["serde", "smol_str/serde"] [dependencies] # bevy @@ -24,10 +24,11 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.12.0", features = [ bevy_utils = { path = "../bevy_utils", version = "0.12.0" } # Used for close_on_esc bevy_input = { path = "../bevy_input", version = "0.12.0" } -raw-window-handle = "0.5" # other serde = { version = "1.0", features = ["derive"], optional = true } +raw-window-handle = "0.5" +smol_str = "0.2" [lints] workspace = true diff --git a/crates/bevy_window/src/cursor.rs b/crates/bevy_window/src/cursor.rs index bf6b5948092aa..1bbf4187ade41 100644 --- a/crates/bevy_window/src/cursor.rs +++ b/crates/bevy_window/src/cursor.rs @@ -1,3 +1,73 @@ +// This file contains a portion of the CSS Basic User Interface Module Level 3 +// specification. In particular, the names for the cursor from the #cursor +// section and documentation for some of the variants were taken. +// +// The original document is https://www.w3.org/TR/css-ui-3/#cursor. +// Copyright © 2018 W3C® (MIT, ERCIM, Keio, Beihang) +// +// These documents were used under the terms of the following license. This W3C +// license as well as the W3C short notice apply to the `CursorIcon` enum's +// variants and documentation attached to them. + +// --------- BEGGINING OF W3C LICENSE +// -------------------------------------------------------------- +// +// License +// +// By obtaining and/or copying this work, you (the licensee) agree that you have +// read, understood, and will comply with the following terms and conditions. +// +// Permission to copy, modify, and distribute this work, with or without +// modification, for any purpose and without fee or royalty is hereby granted, +// provided that you include the following on ALL copies of the work or portions +// thereof, including modifications: +// +// - The full text of this NOTICE in a location viewable to users of the +// redistributed or derivative work. +// - Any pre-existing intellectual property disclaimers, notices, or terms and +// conditions. If none exist, the W3C Software and Document Short Notice +// should be included. +// - Notice of any changes or modifications, through a copyright statement on +// the new code or document such as "This software or document includes +// material copied from or derived from [title and URI of the W3C document]. +// Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." +// +// Disclaimers +// +// THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS +// OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES +// OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF +// THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, +// COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. +// +// COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR +// CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. +// +// The name and trademarks of copyright holders may NOT be used in advertising +// or publicity pertaining to the work without specific, written prior +// permission. Title to copyright in this work will at all times remain with +// copyright holders. +// +// --------- END OF W3C LICENSE +// -------------------------------------------------------------------- + +// --------- BEGGINING OF W3C SHORT NOTICE +// --------------------------------------------------------- +// +// winit: https://github.com/rust-windowing/cursor-icon +// +// Copyright © 2023 World Wide Web Consortium, (Massachusetts Institute of +// Technology, European Research Consortium for Informatics and Mathematics, +// Keio University, Beihang). All Rights Reserved. This work is distributed +// under the W3C® Software License [1] in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// [1] http://www.w3.org/Consortium/Legal/copyright-software +// +// --------- END OF W3C SHORT NOTICE +// -------------------------------------------------------------- + use bevy_reflect::{prelude::ReflectDefault, Reflect}; #[cfg(feature = "serialize")] @@ -20,78 +90,130 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; )] #[reflect(Debug, PartialEq, Default)] pub enum CursorIcon { - /// The platform-dependent default cursor. + /// The platform-dependent default cursor. Often rendered as arrow. #[default] Default, - /// A simple crosshair. - Crosshair, - /// A hand (often used to indicate links in web browsers). - Hand, - /// An arrow. This is the default cursor on most systems. - Arrow, - /// Indicates something is to be moved. - Move, - /// Indicates text that may be selected or edited. - Text, - /// Program busy indicator. - Wait, - /// Help indicator (often rendered as a "?") + + /// A context menu is available for the object under the cursor. Often + /// rendered as an arrow with a small menu-like graphic next to it. + ContextMenu, + + /// Help is available for the object under the cursor. Often rendered as a + /// question mark or a balloon. Help, - /// Progress indicator. Shows that processing is being done. - /// - /// But in contrast with "Wait" the user may still interact with the program. - /// Often rendered as a spinning beach ball, or an arrow with a watch or hourglass. + + /// The cursor is a pointer that indicates a link. Often rendered as the + /// backside of a hand with the index finger extended. + Pointer, + + /// A progress indicator. The program is performing some processing, but is + /// different from [`CursorIcon::Wait`] in that the user may still interact + /// with the program. Progress, - /// Cursor showing that something cannot be done. - NotAllowed, - /// Indicates that a context menu is available. - ContextMenu, - /// Indicates that a cell (or set of cells) may be selected. + + /// Indicates that the program is busy and the user should wait. Often + /// rendered as a watch or hourglass. + Wait, + + /// Indicates that a cell or set of cells may be selected. Often rendered as + /// a thick plus-sign with a dot in the middle. Cell, - /// Indicates vertical text that may be selected or edited. + + /// A simple crosshair (e.g., short line segments resembling a "+" sign). + /// Often used to indicate a two dimensional bitmap selection mode. + Crosshair, + + /// Indicates text that may be selected. Often rendered as an I-beam. + Text, + + /// Indicates vertical-text that may be selected. Often rendered as a + /// horizontal I-beam. VerticalText, - /// Indicates that an alias of something is to be created. + + /// Indicates an alias of/shortcut to something is to be created. Often + /// rendered as an arrow with a small curved arrow next to it. Alias, - /// Indicates something is to be copied. + + /// Indicates something is to be copied. Often rendered as an arrow with a + /// small plus sign next to it. Copy, - /// Indicates that the dragged item cannot be dropped here. + + /// Indicates something is to be moved. + Move, + + /// Indicates that the dragged item cannot be dropped at the current cursor + /// location. Often rendered as a hand or pointer with a small circle with a + /// line through it. NoDrop, - /// Indicates that something can be grabbed. + + /// Indicates that the requested action will not be carried out. Often + /// rendered as a circle with a line through it. + NotAllowed, + + /// Indicates that something can be grabbed (dragged to be moved). Often + /// rendered as the backside of an open hand. Grab, - /// Indicates that something is grabbed. + + /// Indicates that something is being grabbed (dragged to be moved). Often + /// rendered as the backside of a hand with fingers closed mostly out of + /// view. Grabbing, - /// Indicates that the user can scroll by dragging the mouse. - AllScroll, - /// Indicates that the user can zoom in. - ZoomIn, - /// Indicates that the user can zoom out. - ZoomOut, - /// Indicates that an edge of a box is to be moved right (east). + + /// The east border to be moved. EResize, - /// Indicates that an edge of a box is to be moved up (north). + + /// The north border to be moved. NResize, - /// Indicates that an edge of a box is to be moved up and right (north/east). + + /// The north-east corner to be moved. NeResize, - /// indicates that an edge of a box is to be moved up and left (north/west). + + /// The north-west corner to be moved. NwResize, - /// Indicates that an edge of a box is to be moved down (south). + + /// The south border to be moved. SResize, - /// The cursor indicates that an edge of a box is to be moved down and right (south/east). + + /// The south-east corner to be moved. SeResize, - /// The cursor indicates that an edge of a box is to be moved down and left (south/west). + + /// The south-west corner to be moved. SwResize, - /// Indicates that an edge of a box is to be moved left (west). + + /// The west border to be moved. WResize, - /// Indicates a bidirectional resize cursor. + + /// The east and west borders to be moved. EwResize, - /// Indicates a bidirectional resize cursor. + + /// The south and north borders to be moved. NsResize, - /// Indicates a bidirectional resize cursor. + + /// The north-east and south-west corners to be moved. NeswResize, - /// Indicates a bidirectional resize cursor. + + /// The north-west and south-east corners to be moved. NwseResize, - /// Indicates that a column can be resized horizontally. + + /// Indicates that the item/column can be resized horizontally. Often + /// rendered as arrows pointing left and right with a vertical bar + /// separating them. ColResize, - /// Indicates that the row can be resized vertically. + + /// Indicates that the item/row can be resized vertically. Often rendered as + /// arrows pointing up and down with a horizontal bar separating them. RowResize, + + /// Indicates that the something can be scrolled in any direction. Often + /// rendered as arrows pointing up, down, left, and right with a dot in the + /// middle. + AllScroll, + + /// Indicates that something can be zoomed in. Often rendered as a + /// magnifying glass with a "+" in the center of the glass. + ZoomIn, + + /// Indicates that something can be zoomed in. Often rendered as a + /// magnifying glass with a "-" in the center of the glass. + ZoomOut, } diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index 0bd07191cf42c..28e8e19cda3f3 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -4,6 +4,7 @@ use bevy_ecs::entity::Entity; use bevy_ecs::event::Event; use bevy_math::{IVec2, Vec2}; use bevy_reflect::Reflect; +use smol_str::SmolStr; #[cfg(feature = "serialize")] use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; @@ -172,7 +173,7 @@ pub struct ReceivedCharacter { /// Window that received the character. pub window: Entity, /// Received character. - pub char: char, + pub char: SmolStr, } /// A Input Method Editor event. diff --git a/crates/bevy_winit/Cargo.toml b/crates/bevy_winit/Cargo.toml index c16abf9d951e4..1619d02777658 100644 --- a/crates/bevy_winit/Cargo.toml +++ b/crates/bevy_winit/Cargo.toml @@ -28,19 +28,25 @@ bevy_utils = { path = "../bevy_utils", version = "0.12.0" } bevy_tasks = { path = "../bevy_tasks", version = "0.12.0" } # other -winit = { version = "0.28.7", default-features = false } -accesskit_winit = { version = "0.15", default-features = false } +# feature rwh_05 refers to window_raw_handle@v0.5, +# updating to rwh_06 is blocked until wgpu 0.19 release lands. +winit = { version = "0.29", default-features = false, features = ["rwh_05"] } +accesskit_winit = { version = "0.17", default-features = false, features = [ + "rwh_05", +] } approx = { version = "0.5", default-features = false } raw-window-handle = "0.5" [target.'cfg(target_os = "android")'.dependencies] -winit = { version = "0.28.7", default-features = false, features = [ +winit = { version = "0.29", default-features = false, features = [ "android-native-activity", + "rwh_05", ] } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = { version = "0.2" } web-sys = "0.3" + crossbeam-channel = "0.5" [package.metadata.docs.rs] diff --git a/crates/bevy_winit/src/converters.rs b/crates/bevy_winit/src/converters.rs index 85302ecb0d68c..9817d5a4e98ae 100644 --- a/crates/bevy_winit/src/converters.rs +++ b/crates/bevy_winit/src/converters.rs @@ -1,6 +1,6 @@ use bevy_ecs::entity::Entity; use bevy_input::{ - keyboard::{KeyCode, KeyboardInput}, + keyboard::{KeyCode, KeyboardInput, NativeKeyCode}, mouse::MouseButton, touch::{ForceTouch, TouchInput, TouchPhase}, ButtonState, @@ -9,13 +9,12 @@ use bevy_math::Vec2; use bevy_window::{CursorIcon, EnabledButtons, WindowLevel, WindowTheme}; pub fn convert_keyboard_input( - keyboard_input: &winit::event::KeyboardInput, + keyboard_input: &winit::event::KeyEvent, window: Entity, ) -> KeyboardInput { KeyboardInput { - scan_code: keyboard_input.scancode, state: convert_element_state(keyboard_input.state), - key_code: keyboard_input.virtual_keycode.map(convert_virtual_key_code), + key_code: convert_physical_key_code(keyboard_input.physical_key), window, } } @@ -32,6 +31,8 @@ pub fn convert_mouse_button(mouse_button: winit::event::MouseButton) -> MouseBut winit::event::MouseButton::Left => MouseButton::Left, winit::event::MouseButton::Right => MouseButton::Right, winit::event::MouseButton::Middle => MouseButton::Middle, + winit::event::MouseButton::Back => MouseButton::Back, + winit::event::MouseButton::Forward => MouseButton::Forward, winit::event::MouseButton::Other(val) => MouseButton::Other(val), } } @@ -64,180 +65,226 @@ pub fn convert_touch_input( } } -pub fn convert_virtual_key_code(virtual_key_code: winit::event::VirtualKeyCode) -> KeyCode { +pub fn convert_physical_native_key_code( + native_key_code: winit::keyboard::NativeKeyCode, +) -> NativeKeyCode { + match native_key_code { + winit::keyboard::NativeKeyCode::Unidentified => NativeKeyCode::Unidentified, + winit::keyboard::NativeKeyCode::Android(scan_code) => NativeKeyCode::Android(scan_code), + winit::keyboard::NativeKeyCode::MacOS(scan_code) => NativeKeyCode::MacOS(scan_code), + winit::keyboard::NativeKeyCode::Windows(scan_code) => NativeKeyCode::Windows(scan_code), + winit::keyboard::NativeKeyCode::Xkb(key_code) => NativeKeyCode::Xkb(key_code), + } +} +pub fn convert_physical_key_code(virtual_key_code: winit::keyboard::PhysicalKey) -> KeyCode { match virtual_key_code { - winit::event::VirtualKeyCode::Key1 => KeyCode::Key1, - winit::event::VirtualKeyCode::Key2 => KeyCode::Key2, - winit::event::VirtualKeyCode::Key3 => KeyCode::Key3, - winit::event::VirtualKeyCode::Key4 => KeyCode::Key4, - winit::event::VirtualKeyCode::Key5 => KeyCode::Key5, - winit::event::VirtualKeyCode::Key6 => KeyCode::Key6, - winit::event::VirtualKeyCode::Key7 => KeyCode::Key7, - winit::event::VirtualKeyCode::Key8 => KeyCode::Key8, - winit::event::VirtualKeyCode::Key9 => KeyCode::Key9, - winit::event::VirtualKeyCode::Key0 => KeyCode::Key0, - winit::event::VirtualKeyCode::A => KeyCode::A, - winit::event::VirtualKeyCode::B => KeyCode::B, - winit::event::VirtualKeyCode::C => KeyCode::C, - winit::event::VirtualKeyCode::D => KeyCode::D, - winit::event::VirtualKeyCode::E => KeyCode::E, - winit::event::VirtualKeyCode::F => KeyCode::F, - winit::event::VirtualKeyCode::G => KeyCode::G, - winit::event::VirtualKeyCode::H => KeyCode::H, - winit::event::VirtualKeyCode::I => KeyCode::I, - winit::event::VirtualKeyCode::J => KeyCode::J, - winit::event::VirtualKeyCode::K => KeyCode::K, - winit::event::VirtualKeyCode::L => KeyCode::L, - winit::event::VirtualKeyCode::M => KeyCode::M, - winit::event::VirtualKeyCode::N => KeyCode::N, - winit::event::VirtualKeyCode::O => KeyCode::O, - winit::event::VirtualKeyCode::P => KeyCode::P, - winit::event::VirtualKeyCode::Q => KeyCode::Q, - winit::event::VirtualKeyCode::R => KeyCode::R, - winit::event::VirtualKeyCode::S => KeyCode::S, - winit::event::VirtualKeyCode::T => KeyCode::T, - winit::event::VirtualKeyCode::U => KeyCode::U, - winit::event::VirtualKeyCode::V => KeyCode::V, - winit::event::VirtualKeyCode::W => KeyCode::W, - winit::event::VirtualKeyCode::X => KeyCode::X, - winit::event::VirtualKeyCode::Y => KeyCode::Y, - winit::event::VirtualKeyCode::Z => KeyCode::Z, - winit::event::VirtualKeyCode::Escape => KeyCode::Escape, - winit::event::VirtualKeyCode::F1 => KeyCode::F1, - winit::event::VirtualKeyCode::F2 => KeyCode::F2, - winit::event::VirtualKeyCode::F3 => KeyCode::F3, - winit::event::VirtualKeyCode::F4 => KeyCode::F4, - winit::event::VirtualKeyCode::F5 => KeyCode::F5, - winit::event::VirtualKeyCode::F6 => KeyCode::F6, - winit::event::VirtualKeyCode::F7 => KeyCode::F7, - winit::event::VirtualKeyCode::F8 => KeyCode::F8, - winit::event::VirtualKeyCode::F9 => KeyCode::F9, - winit::event::VirtualKeyCode::F10 => KeyCode::F10, - winit::event::VirtualKeyCode::F11 => KeyCode::F11, - winit::event::VirtualKeyCode::F12 => KeyCode::F12, - winit::event::VirtualKeyCode::F13 => KeyCode::F13, - winit::event::VirtualKeyCode::F14 => KeyCode::F14, - winit::event::VirtualKeyCode::F15 => KeyCode::F15, - winit::event::VirtualKeyCode::F16 => KeyCode::F16, - winit::event::VirtualKeyCode::F17 => KeyCode::F17, - winit::event::VirtualKeyCode::F18 => KeyCode::F18, - winit::event::VirtualKeyCode::F19 => KeyCode::F19, - winit::event::VirtualKeyCode::F20 => KeyCode::F20, - winit::event::VirtualKeyCode::F21 => KeyCode::F21, - winit::event::VirtualKeyCode::F22 => KeyCode::F22, - winit::event::VirtualKeyCode::F23 => KeyCode::F23, - winit::event::VirtualKeyCode::F24 => KeyCode::F24, - winit::event::VirtualKeyCode::Snapshot => KeyCode::Snapshot, - winit::event::VirtualKeyCode::Scroll => KeyCode::Scroll, - winit::event::VirtualKeyCode::Pause => KeyCode::Pause, - winit::event::VirtualKeyCode::Insert => KeyCode::Insert, - winit::event::VirtualKeyCode::Home => KeyCode::Home, - winit::event::VirtualKeyCode::Delete => KeyCode::Delete, - winit::event::VirtualKeyCode::End => KeyCode::End, - winit::event::VirtualKeyCode::PageDown => KeyCode::PageDown, - winit::event::VirtualKeyCode::PageUp => KeyCode::PageUp, - winit::event::VirtualKeyCode::Left => KeyCode::Left, - winit::event::VirtualKeyCode::Up => KeyCode::Up, - winit::event::VirtualKeyCode::Right => KeyCode::Right, - winit::event::VirtualKeyCode::Down => KeyCode::Down, - winit::event::VirtualKeyCode::Back => KeyCode::Back, - winit::event::VirtualKeyCode::Return => KeyCode::Return, - winit::event::VirtualKeyCode::Space => KeyCode::Space, - winit::event::VirtualKeyCode::Compose => KeyCode::Compose, - winit::event::VirtualKeyCode::Caret => KeyCode::Caret, - winit::event::VirtualKeyCode::Numlock => KeyCode::Numlock, - winit::event::VirtualKeyCode::Numpad0 => KeyCode::Numpad0, - winit::event::VirtualKeyCode::Numpad1 => KeyCode::Numpad1, - winit::event::VirtualKeyCode::Numpad2 => KeyCode::Numpad2, - winit::event::VirtualKeyCode::Numpad3 => KeyCode::Numpad3, - winit::event::VirtualKeyCode::Numpad4 => KeyCode::Numpad4, - winit::event::VirtualKeyCode::Numpad5 => KeyCode::Numpad5, - winit::event::VirtualKeyCode::Numpad6 => KeyCode::Numpad6, - winit::event::VirtualKeyCode::Numpad7 => KeyCode::Numpad7, - winit::event::VirtualKeyCode::Numpad8 => KeyCode::Numpad8, - winit::event::VirtualKeyCode::Numpad9 => KeyCode::Numpad9, - winit::event::VirtualKeyCode::AbntC1 => KeyCode::AbntC1, - winit::event::VirtualKeyCode::AbntC2 => KeyCode::AbntC2, - winit::event::VirtualKeyCode::NumpadAdd => KeyCode::NumpadAdd, - winit::event::VirtualKeyCode::Apostrophe => KeyCode::Apostrophe, - winit::event::VirtualKeyCode::Apps => KeyCode::Apps, - winit::event::VirtualKeyCode::Asterisk => KeyCode::Asterisk, - winit::event::VirtualKeyCode::Plus => KeyCode::Plus, - winit::event::VirtualKeyCode::At => KeyCode::At, - winit::event::VirtualKeyCode::Ax => KeyCode::Ax, - winit::event::VirtualKeyCode::Backslash => KeyCode::Backslash, - winit::event::VirtualKeyCode::Calculator => KeyCode::Calculator, - winit::event::VirtualKeyCode::Capital => KeyCode::Capital, - winit::event::VirtualKeyCode::Colon => KeyCode::Colon, - winit::event::VirtualKeyCode::Comma => KeyCode::Comma, - winit::event::VirtualKeyCode::Convert => KeyCode::Convert, - winit::event::VirtualKeyCode::NumpadDecimal => KeyCode::NumpadDecimal, - winit::event::VirtualKeyCode::NumpadDivide => KeyCode::NumpadDivide, - winit::event::VirtualKeyCode::Equals => KeyCode::Equals, - winit::event::VirtualKeyCode::Grave => KeyCode::Grave, - winit::event::VirtualKeyCode::Kana => KeyCode::Kana, - winit::event::VirtualKeyCode::Kanji => KeyCode::Kanji, - winit::event::VirtualKeyCode::LAlt => KeyCode::AltLeft, - winit::event::VirtualKeyCode::LBracket => KeyCode::BracketLeft, - winit::event::VirtualKeyCode::LControl => KeyCode::ControlLeft, - winit::event::VirtualKeyCode::LShift => KeyCode::ShiftLeft, - winit::event::VirtualKeyCode::LWin => KeyCode::SuperLeft, - winit::event::VirtualKeyCode::Mail => KeyCode::Mail, - winit::event::VirtualKeyCode::MediaSelect => KeyCode::MediaSelect, - winit::event::VirtualKeyCode::MediaStop => KeyCode::MediaStop, - winit::event::VirtualKeyCode::Minus => KeyCode::Minus, - winit::event::VirtualKeyCode::NumpadMultiply => KeyCode::NumpadMultiply, - winit::event::VirtualKeyCode::Mute => KeyCode::Mute, - winit::event::VirtualKeyCode::MyComputer => KeyCode::MyComputer, - winit::event::VirtualKeyCode::NavigateForward => KeyCode::NavigateForward, - winit::event::VirtualKeyCode::NavigateBackward => KeyCode::NavigateBackward, - winit::event::VirtualKeyCode::NextTrack => KeyCode::NextTrack, - winit::event::VirtualKeyCode::NoConvert => KeyCode::NoConvert, - winit::event::VirtualKeyCode::NumpadComma => KeyCode::NumpadComma, - winit::event::VirtualKeyCode::NumpadEnter => KeyCode::NumpadEnter, - winit::event::VirtualKeyCode::NumpadEquals => KeyCode::NumpadEquals, - winit::event::VirtualKeyCode::OEM102 => KeyCode::Oem102, - winit::event::VirtualKeyCode::Period => KeyCode::Period, - winit::event::VirtualKeyCode::PlayPause => KeyCode::PlayPause, - winit::event::VirtualKeyCode::Power => KeyCode::Power, - winit::event::VirtualKeyCode::PrevTrack => KeyCode::PrevTrack, - winit::event::VirtualKeyCode::RAlt => KeyCode::AltRight, - winit::event::VirtualKeyCode::RBracket => KeyCode::BracketRight, - winit::event::VirtualKeyCode::RControl => KeyCode::ControlRight, - winit::event::VirtualKeyCode::RShift => KeyCode::ShiftRight, - winit::event::VirtualKeyCode::RWin => KeyCode::SuperRight, - winit::event::VirtualKeyCode::Semicolon => KeyCode::Semicolon, - winit::event::VirtualKeyCode::Slash => KeyCode::Slash, - winit::event::VirtualKeyCode::Sleep => KeyCode::Sleep, - winit::event::VirtualKeyCode::Stop => KeyCode::Stop, - winit::event::VirtualKeyCode::NumpadSubtract => KeyCode::NumpadSubtract, - winit::event::VirtualKeyCode::Sysrq => KeyCode::Sysrq, - winit::event::VirtualKeyCode::Tab => KeyCode::Tab, - winit::event::VirtualKeyCode::Underline => KeyCode::Underline, - winit::event::VirtualKeyCode::Unlabeled => KeyCode::Unlabeled, - winit::event::VirtualKeyCode::VolumeDown => KeyCode::VolumeDown, - winit::event::VirtualKeyCode::VolumeUp => KeyCode::VolumeUp, - winit::event::VirtualKeyCode::Wake => KeyCode::Wake, - winit::event::VirtualKeyCode::WebBack => KeyCode::WebBack, - winit::event::VirtualKeyCode::WebFavorites => KeyCode::WebFavorites, - winit::event::VirtualKeyCode::WebForward => KeyCode::WebForward, - winit::event::VirtualKeyCode::WebHome => KeyCode::WebHome, - winit::event::VirtualKeyCode::WebRefresh => KeyCode::WebRefresh, - winit::event::VirtualKeyCode::WebSearch => KeyCode::WebSearch, - winit::event::VirtualKeyCode::WebStop => KeyCode::WebStop, - winit::event::VirtualKeyCode::Yen => KeyCode::Yen, - winit::event::VirtualKeyCode::Copy => KeyCode::Copy, - winit::event::VirtualKeyCode::Paste => KeyCode::Paste, - winit::event::VirtualKeyCode::Cut => KeyCode::Cut, + winit::keyboard::PhysicalKey::Unidentified(native_key_code) => { + KeyCode::Unidentified(convert_physical_native_key_code(native_key_code)) + } + winit::keyboard::PhysicalKey::Code(code) => match code { + winit::keyboard::KeyCode::Backquote => KeyCode::Backquote, + winit::keyboard::KeyCode::Backslash => KeyCode::Backslash, + winit::keyboard::KeyCode::BracketLeft => KeyCode::BracketLeft, + winit::keyboard::KeyCode::BracketRight => KeyCode::BracketRight, + winit::keyboard::KeyCode::Comma => KeyCode::Comma, + winit::keyboard::KeyCode::Digit0 => KeyCode::Digit0, + winit::keyboard::KeyCode::Digit1 => KeyCode::Digit1, + winit::keyboard::KeyCode::Digit2 => KeyCode::Digit2, + winit::keyboard::KeyCode::Digit3 => KeyCode::Digit3, + winit::keyboard::KeyCode::Digit4 => KeyCode::Digit4, + winit::keyboard::KeyCode::Digit5 => KeyCode::Digit5, + winit::keyboard::KeyCode::Digit6 => KeyCode::Digit6, + winit::keyboard::KeyCode::Digit7 => KeyCode::Digit7, + winit::keyboard::KeyCode::Digit8 => KeyCode::Digit8, + winit::keyboard::KeyCode::Digit9 => KeyCode::Digit9, + winit::keyboard::KeyCode::Equal => KeyCode::Equal, + winit::keyboard::KeyCode::IntlBackslash => KeyCode::IntlBackslash, + winit::keyboard::KeyCode::IntlRo => KeyCode::IntlRo, + winit::keyboard::KeyCode::IntlYen => KeyCode::IntlYen, + winit::keyboard::KeyCode::KeyA => KeyCode::KeyA, + winit::keyboard::KeyCode::KeyB => KeyCode::KeyB, + winit::keyboard::KeyCode::KeyC => KeyCode::KeyC, + winit::keyboard::KeyCode::KeyD => KeyCode::KeyD, + winit::keyboard::KeyCode::KeyE => KeyCode::KeyE, + winit::keyboard::KeyCode::KeyF => KeyCode::KeyF, + winit::keyboard::KeyCode::KeyG => KeyCode::KeyG, + winit::keyboard::KeyCode::KeyH => KeyCode::KeyH, + winit::keyboard::KeyCode::KeyI => KeyCode::KeyI, + winit::keyboard::KeyCode::KeyJ => KeyCode::KeyJ, + winit::keyboard::KeyCode::KeyK => KeyCode::KeyK, + winit::keyboard::KeyCode::KeyL => KeyCode::KeyL, + winit::keyboard::KeyCode::KeyM => KeyCode::KeyM, + winit::keyboard::KeyCode::KeyN => KeyCode::KeyN, + winit::keyboard::KeyCode::KeyO => KeyCode::KeyO, + winit::keyboard::KeyCode::KeyP => KeyCode::KeyP, + winit::keyboard::KeyCode::KeyQ => KeyCode::KeyQ, + winit::keyboard::KeyCode::KeyR => KeyCode::KeyR, + winit::keyboard::KeyCode::KeyS => KeyCode::KeyS, + winit::keyboard::KeyCode::KeyT => KeyCode::KeyT, + winit::keyboard::KeyCode::KeyU => KeyCode::KeyU, + winit::keyboard::KeyCode::KeyV => KeyCode::KeyV, + winit::keyboard::KeyCode::KeyW => KeyCode::KeyW, + winit::keyboard::KeyCode::KeyX => KeyCode::KeyX, + winit::keyboard::KeyCode::KeyY => KeyCode::KeyY, + winit::keyboard::KeyCode::KeyZ => KeyCode::KeyZ, + winit::keyboard::KeyCode::Minus => KeyCode::Minus, + winit::keyboard::KeyCode::Period => KeyCode::Period, + winit::keyboard::KeyCode::Quote => KeyCode::Quote, + winit::keyboard::KeyCode::Semicolon => KeyCode::Semicolon, + winit::keyboard::KeyCode::Slash => KeyCode::Slash, + winit::keyboard::KeyCode::AltLeft => KeyCode::AltLeft, + winit::keyboard::KeyCode::AltRight => KeyCode::AltRight, + winit::keyboard::KeyCode::Backspace => KeyCode::Backspace, + winit::keyboard::KeyCode::CapsLock => KeyCode::CapsLock, + winit::keyboard::KeyCode::ContextMenu => KeyCode::ContextMenu, + winit::keyboard::KeyCode::ControlLeft => KeyCode::ControlLeft, + winit::keyboard::KeyCode::ControlRight => KeyCode::ControlRight, + winit::keyboard::KeyCode::Enter => KeyCode::Enter, + winit::keyboard::KeyCode::SuperLeft => KeyCode::SuperLeft, + winit::keyboard::KeyCode::SuperRight => KeyCode::SuperRight, + winit::keyboard::KeyCode::ShiftLeft => KeyCode::ShiftLeft, + winit::keyboard::KeyCode::ShiftRight => KeyCode::ShiftRight, + winit::keyboard::KeyCode::Space => KeyCode::Space, + winit::keyboard::KeyCode::Tab => KeyCode::Tab, + winit::keyboard::KeyCode::Convert => KeyCode::Convert, + winit::keyboard::KeyCode::KanaMode => KeyCode::KanaMode, + winit::keyboard::KeyCode::Lang1 => KeyCode::Lang1, + winit::keyboard::KeyCode::Lang2 => KeyCode::Lang2, + winit::keyboard::KeyCode::Lang3 => KeyCode::Lang3, + winit::keyboard::KeyCode::Lang4 => KeyCode::Lang4, + winit::keyboard::KeyCode::Lang5 => KeyCode::Lang5, + winit::keyboard::KeyCode::NonConvert => KeyCode::NonConvert, + winit::keyboard::KeyCode::Delete => KeyCode::Delete, + winit::keyboard::KeyCode::End => KeyCode::End, + winit::keyboard::KeyCode::Help => KeyCode::Help, + winit::keyboard::KeyCode::Home => KeyCode::Home, + winit::keyboard::KeyCode::Insert => KeyCode::Insert, + winit::keyboard::KeyCode::PageDown => KeyCode::PageDown, + winit::keyboard::KeyCode::PageUp => KeyCode::PageUp, + winit::keyboard::KeyCode::ArrowDown => KeyCode::ArrowDown, + winit::keyboard::KeyCode::ArrowLeft => KeyCode::ArrowLeft, + winit::keyboard::KeyCode::ArrowRight => KeyCode::ArrowRight, + winit::keyboard::KeyCode::ArrowUp => KeyCode::ArrowUp, + winit::keyboard::KeyCode::NumLock => KeyCode::NumLock, + winit::keyboard::KeyCode::Numpad0 => KeyCode::Numpad0, + winit::keyboard::KeyCode::Numpad1 => KeyCode::Numpad1, + winit::keyboard::KeyCode::Numpad2 => KeyCode::Numpad2, + winit::keyboard::KeyCode::Numpad3 => KeyCode::Numpad3, + winit::keyboard::KeyCode::Numpad4 => KeyCode::Numpad4, + winit::keyboard::KeyCode::Numpad5 => KeyCode::Numpad5, + winit::keyboard::KeyCode::Numpad6 => KeyCode::Numpad6, + winit::keyboard::KeyCode::Numpad7 => KeyCode::Numpad7, + winit::keyboard::KeyCode::Numpad8 => KeyCode::Numpad8, + winit::keyboard::KeyCode::Numpad9 => KeyCode::Numpad9, + winit::keyboard::KeyCode::NumpadAdd => KeyCode::NumpadAdd, + winit::keyboard::KeyCode::NumpadBackspace => KeyCode::NumpadBackspace, + winit::keyboard::KeyCode::NumpadClear => KeyCode::NumpadClear, + winit::keyboard::KeyCode::NumpadClearEntry => KeyCode::NumpadClearEntry, + winit::keyboard::KeyCode::NumpadComma => KeyCode::NumpadComma, + winit::keyboard::KeyCode::NumpadDecimal => KeyCode::NumpadDecimal, + winit::keyboard::KeyCode::NumpadDivide => KeyCode::NumpadDivide, + winit::keyboard::KeyCode::NumpadEnter => KeyCode::NumpadEnter, + winit::keyboard::KeyCode::NumpadEqual => KeyCode::NumpadEqual, + winit::keyboard::KeyCode::NumpadHash => KeyCode::NumpadHash, + winit::keyboard::KeyCode::NumpadMemoryAdd => KeyCode::NumpadMemoryAdd, + winit::keyboard::KeyCode::NumpadMemoryClear => KeyCode::NumpadMemoryClear, + winit::keyboard::KeyCode::NumpadMemoryRecall => KeyCode::NumpadMemoryRecall, + winit::keyboard::KeyCode::NumpadMemoryStore => KeyCode::NumpadMemoryStore, + winit::keyboard::KeyCode::NumpadMemorySubtract => KeyCode::NumpadMemorySubtract, + winit::keyboard::KeyCode::NumpadMultiply => KeyCode::NumpadMultiply, + winit::keyboard::KeyCode::NumpadParenLeft => KeyCode::NumpadParenLeft, + winit::keyboard::KeyCode::NumpadParenRight => KeyCode::NumpadParenRight, + winit::keyboard::KeyCode::NumpadStar => KeyCode::NumpadStar, + winit::keyboard::KeyCode::NumpadSubtract => KeyCode::NumpadSubtract, + winit::keyboard::KeyCode::Escape => KeyCode::Escape, + winit::keyboard::KeyCode::Fn => KeyCode::Fn, + winit::keyboard::KeyCode::FnLock => KeyCode::FnLock, + winit::keyboard::KeyCode::PrintScreen => KeyCode::PrintScreen, + winit::keyboard::KeyCode::ScrollLock => KeyCode::ScrollLock, + winit::keyboard::KeyCode::Pause => KeyCode::Pause, + winit::keyboard::KeyCode::BrowserBack => KeyCode::BrowserBack, + winit::keyboard::KeyCode::BrowserFavorites => KeyCode::BrowserFavorites, + winit::keyboard::KeyCode::BrowserForward => KeyCode::BrowserForward, + winit::keyboard::KeyCode::BrowserHome => KeyCode::BrowserHome, + winit::keyboard::KeyCode::BrowserRefresh => KeyCode::BrowserRefresh, + winit::keyboard::KeyCode::BrowserSearch => KeyCode::BrowserSearch, + winit::keyboard::KeyCode::BrowserStop => KeyCode::BrowserStop, + winit::keyboard::KeyCode::Eject => KeyCode::Eject, + winit::keyboard::KeyCode::LaunchApp1 => KeyCode::LaunchApp1, + winit::keyboard::KeyCode::LaunchApp2 => KeyCode::LaunchApp2, + winit::keyboard::KeyCode::LaunchMail => KeyCode::LaunchMail, + winit::keyboard::KeyCode::MediaPlayPause => KeyCode::MediaPlayPause, + winit::keyboard::KeyCode::MediaSelect => KeyCode::MediaSelect, + winit::keyboard::KeyCode::MediaStop => KeyCode::MediaStop, + winit::keyboard::KeyCode::MediaTrackNext => KeyCode::MediaTrackNext, + winit::keyboard::KeyCode::MediaTrackPrevious => KeyCode::MediaTrackPrevious, + winit::keyboard::KeyCode::Power => KeyCode::Power, + winit::keyboard::KeyCode::Sleep => KeyCode::Sleep, + winit::keyboard::KeyCode::AudioVolumeDown => KeyCode::AudioVolumeDown, + winit::keyboard::KeyCode::AudioVolumeMute => KeyCode::AudioVolumeMute, + winit::keyboard::KeyCode::AudioVolumeUp => KeyCode::AudioVolumeUp, + winit::keyboard::KeyCode::WakeUp => KeyCode::WakeUp, + winit::keyboard::KeyCode::Meta => KeyCode::Meta, + winit::keyboard::KeyCode::Hyper => KeyCode::Hyper, + winit::keyboard::KeyCode::Turbo => KeyCode::Turbo, + winit::keyboard::KeyCode::Abort => KeyCode::Abort, + winit::keyboard::KeyCode::Resume => KeyCode::Resume, + winit::keyboard::KeyCode::Suspend => KeyCode::Suspend, + winit::keyboard::KeyCode::Again => KeyCode::Again, + winit::keyboard::KeyCode::Copy => KeyCode::Copy, + winit::keyboard::KeyCode::Cut => KeyCode::Cut, + winit::keyboard::KeyCode::Find => KeyCode::Find, + winit::keyboard::KeyCode::Open => KeyCode::Open, + winit::keyboard::KeyCode::Paste => KeyCode::Paste, + winit::keyboard::KeyCode::Props => KeyCode::Props, + winit::keyboard::KeyCode::Select => KeyCode::Select, + winit::keyboard::KeyCode::Undo => KeyCode::Undo, + winit::keyboard::KeyCode::Hiragana => KeyCode::Hiragana, + winit::keyboard::KeyCode::Katakana => KeyCode::Katakana, + winit::keyboard::KeyCode::F1 => KeyCode::F1, + winit::keyboard::KeyCode::F2 => KeyCode::F2, + winit::keyboard::KeyCode::F3 => KeyCode::F3, + winit::keyboard::KeyCode::F4 => KeyCode::F4, + winit::keyboard::KeyCode::F5 => KeyCode::F5, + winit::keyboard::KeyCode::F6 => KeyCode::F6, + winit::keyboard::KeyCode::F7 => KeyCode::F7, + winit::keyboard::KeyCode::F8 => KeyCode::F8, + winit::keyboard::KeyCode::F9 => KeyCode::F9, + winit::keyboard::KeyCode::F10 => KeyCode::F10, + winit::keyboard::KeyCode::F11 => KeyCode::F11, + winit::keyboard::KeyCode::F12 => KeyCode::F12, + winit::keyboard::KeyCode::F13 => KeyCode::F13, + winit::keyboard::KeyCode::F14 => KeyCode::F14, + winit::keyboard::KeyCode::F15 => KeyCode::F15, + winit::keyboard::KeyCode::F16 => KeyCode::F16, + winit::keyboard::KeyCode::F17 => KeyCode::F17, + winit::keyboard::KeyCode::F18 => KeyCode::F18, + winit::keyboard::KeyCode::F19 => KeyCode::F19, + winit::keyboard::KeyCode::F20 => KeyCode::F20, + winit::keyboard::KeyCode::F21 => KeyCode::F21, + winit::keyboard::KeyCode::F22 => KeyCode::F22, + winit::keyboard::KeyCode::F23 => KeyCode::F23, + winit::keyboard::KeyCode::F24 => KeyCode::F24, + winit::keyboard::KeyCode::F25 => KeyCode::F25, + winit::keyboard::KeyCode::F26 => KeyCode::F26, + winit::keyboard::KeyCode::F27 => KeyCode::F27, + winit::keyboard::KeyCode::F28 => KeyCode::F28, + winit::keyboard::KeyCode::F29 => KeyCode::F29, + winit::keyboard::KeyCode::F30 => KeyCode::F30, + winit::keyboard::KeyCode::F31 => KeyCode::F31, + winit::keyboard::KeyCode::F32 => KeyCode::F32, + winit::keyboard::KeyCode::F33 => KeyCode::F33, + winit::keyboard::KeyCode::F34 => KeyCode::F34, + winit::keyboard::KeyCode::F35 => KeyCode::F35, + _ => KeyCode::Unidentified(NativeKeyCode::Unidentified), + }, } } pub fn convert_cursor_icon(cursor_icon: CursorIcon) -> winit::window::CursorIcon { match cursor_icon { - CursorIcon::Default => winit::window::CursorIcon::Default, CursorIcon::Crosshair => winit::window::CursorIcon::Crosshair, - CursorIcon::Hand => winit::window::CursorIcon::Hand, - CursorIcon::Arrow => winit::window::CursorIcon::Arrow, + CursorIcon::Pointer => winit::window::CursorIcon::Pointer, CursorIcon::Move => winit::window::CursorIcon::Move, CursorIcon::Text => winit::window::CursorIcon::Text, CursorIcon::Wait => winit::window::CursorIcon::Wait, @@ -269,6 +316,7 @@ pub fn convert_cursor_icon(cursor_icon: CursorIcon) -> winit::window::CursorIcon CursorIcon::NwseResize => winit::window::CursorIcon::NwseResize, CursorIcon::ColResize => winit::window::CursorIcon::ColResize, CursorIcon::RowResize => winit::window::CursorIcon::RowResize, + _ => winit::window::CursorIcon::Default, } } diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index ef155f220f8cb..6a320bb2f6e09 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -15,6 +15,7 @@ mod winit_config; mod winit_windows; use bevy_a11y::AccessibilityRequested; +use bevy_utils::{Duration, Instant}; use system::{changed_windows, create_windows, despawn_windows, CachedWindow}; pub use winit_config::*; pub use winit_windows::*; @@ -32,10 +33,7 @@ use bevy_input::{ use bevy_math::{ivec2, DVec2, Vec2}; #[cfg(not(target_arch = "wasm32"))] use bevy_tasks::tick_global_task_pools_on_main_thread; -use bevy_utils::{ - tracing::{trace, warn}, - Duration, Instant, -}; +use bevy_utils::tracing::{error, trace, warn}; use bevy_window::{ exit_on_all_closed, ApplicationLifetime, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, Ime, ReceivedCharacter, RequestRedraw, Window, @@ -148,7 +146,9 @@ impl Plugin for WinitPlugin { #[cfg(target_arch = "wasm32")] app.add_plugins(CanvasParentResizePlugin); - let event_loop = event_loop_builder.build(); + let event_loop = event_loop_builder + .build() + .expect("Failed to build event loop"); // iOS, macOS, and Android don't like it if you create windows before the event loop is // initialized. @@ -229,46 +229,6 @@ impl Plugin for WinitPlugin { } } -fn run(event_loop: EventLoop, event_handler: F) -> ! -where - F: 'static + FnMut(Event<'_, T>, &EventLoopWindowTarget, &mut ControlFlow), -{ - event_loop.run(event_handler) -} - -#[cfg(any( - target_os = "windows", - target_os = "macos", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd" -))] -fn run_return(event_loop: &mut EventLoop, event_handler: F) -where - F: FnMut(Event<'_, T>, &EventLoopWindowTarget, &mut ControlFlow), -{ - use winit::platform::run_return::EventLoopExtRunReturn; - event_loop.run_return(event_handler); -} - -#[cfg(not(any( - target_os = "windows", - target_os = "macos", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd" -)))] -fn run_return(_event_loop: &mut EventLoop, _event_handler: F) -where - F: FnMut(Event<'_, T>, &EventLoopWindowTarget, &mut ControlFlow), -{ - panic!("Run return is not supported on this platform!") -} - #[derive(SystemParam)] struct WindowAndInputEventWriters<'w> { // `winit` `WindowEvent`s @@ -356,13 +316,11 @@ pub fn winit_runner(mut app: App) { app.cleanup(); } - let mut event_loop = app + let event_loop = app .world .remove_non_send_resource::>() .unwrap(); - let return_from_run = app.world.resource::().return_from_run; - app.world .insert_non_send_resource(event_loop.create_proxy()); @@ -406,9 +364,7 @@ pub fn winit_runner(mut app: App) { )> = SystemState::from_world(&mut app.world); // setup up the event loop - let event_handler = move |event: Event<()>, - event_loop: &EventLoopWindowTarget<()>, - control_flow: &mut ControlFlow| { + let event_handler = move |event: Event<()>, event_loop: &EventLoopWindowTarget<()>| { #[cfg(feature = "trace")] let _span = bevy_utils::tracing::info_span!("winit event_handler").entered(); @@ -423,7 +379,7 @@ pub fn winit_runner(mut app: App) { if let Some(app_exit_events) = app.world.get_resource::>() { if app_exit_event_reader.read(app_exit_events).last().is_some() { - *control_flow = ControlFlow::Exit; + event_loop.exit(); return; } } @@ -507,11 +463,7 @@ pub fn winit_runner(mut app: App) { // the engine. if let Some(adapter) = access_kit_adapters.get(&window_entity) { if let Some(window) = winit_windows.get_window(window_entity) { - // Somewhat surprisingly, this call has meaningful side effects - // See https://github.com/AccessKit/accesskit/issues/300 - // AccessKit might later need to filter events based on this, but we currently do not. - // See https://github.com/bevyengine/bevy/pull/10239#issuecomment-1775572176 - let _ = adapter.on_event(window, &event); + adapter.process_event(window, &event); } } @@ -519,15 +471,7 @@ pub fn winit_runner(mut app: App) { match event { WindowEvent::Resized(size) => { - window - .resolution - .set_physical_resolution(size.width, size.height); - - event_writers.window_resized.send(WindowResized { - window: window_entity, - width: window.width(), - height: window.height(), - }); + react_to_resize(&mut window, size, &mut event_writers, window_entity); } WindowEvent::CloseRequested => { event_writers @@ -536,10 +480,18 @@ pub fn winit_runner(mut app: App) { window: window_entity, }); } - WindowEvent::KeyboardInput { ref input, .. } => { - event_writers - .keyboard_input - .send(converters::convert_keyboard_input(input, window_entity)); + WindowEvent::KeyboardInput { ref event, .. } => { + if event.state.is_pressed() { + if let Some(char) = &event.text { + event_writers.character_input.send(ReceivedCharacter { + window: window_entity, + char: char.clone(), + }); + } + } + let keyboard_event = + converters::convert_keyboard_input(event, window_entity); + event_writers.keyboard_input.send(keyboard_event); } WindowEvent::CursorMoved { position, .. } => { let physical_position = DVec2::new(position.x, position.y); @@ -604,15 +556,9 @@ pub fn winit_runner(mut app: App) { .touch_input .send(converters::convert_touch_input(touch, location)); } - WindowEvent::ReceivedCharacter(char) => { - event_writers.character_input.send(ReceivedCharacter { - window: window_entity, - char, - }); - } WindowEvent::ScaleFactorChanged { scale_factor, - new_inner_size, + mut inner_size_writer, } => { event_writers.window_backend_scale_factor_changed.send( WindowBackendScaleFactorChanged { @@ -625,13 +571,22 @@ pub fn winit_runner(mut app: App) { window.resolution.set_scale_factor(scale_factor as f32); let new_factor = window.resolution.scale_factor(); + let mut new_inner_size = winit::dpi::PhysicalSize::new( + window.physical_width(), + window.physical_height(), + ); if let Some(forced_factor) = window.resolution.scale_factor_override() { // This window is overriding the OS-suggested DPI, so its physical size // should be set based on the overriding value. Its logical size already // incorporates any resize constraints. - *new_inner_size = + let maybe_new_inner_size = winit::dpi::LogicalSize::new(window.width(), window.height()) .to_physical::(forced_factor as f64); + if let Err(err) = inner_size_writer.request_inner_size(new_inner_size) { + warn!("Winit Failed to resize the window: {err}"); + } else { + new_inner_size = maybe_new_inner_size; + } } else if approx::relative_ne!(new_factor, prior_factor) { event_writers.window_scale_factor_changed.send( WindowScaleFactorChanged { @@ -640,7 +595,6 @@ pub fn winit_runner(mut app: App) { }, ); } - let new_logical_width = new_inner_size.width as f32 / new_factor; let new_logical_height = new_inner_size.height as f32 / new_factor; if approx::relative_ne!(window.width(), new_logical_width) @@ -807,10 +761,10 @@ pub fn winit_runner(mut app: App) { app.world.entity_mut(entity).insert(wrapper); } - *control_flow = ControlFlow::Poll; + event_loop.set_control_flow(ControlFlow::Poll); } } - Event::MainEventsCleared => { + Event::AboutToWait => { if runner_state.active.should_run() { if runner_state.active == ActiveState::WillSuspend { runner_state.active = ActiveState::Suspended; @@ -822,7 +776,7 @@ pub fn winit_runner(mut app: App) { app.world.query_filtered::>(); let entity = query.single(&app.world); app.world.entity_mut(entity).remove::(); - *control_flow = ControlFlow::Wait; + event_loop.set_control_flow(ControlFlow::Wait); } } let (config, windows) = focused_windows_state.get(&app.world); @@ -855,15 +809,17 @@ pub fn winit_runner(mut app: App) { let (config, windows) = focused_windows_state.get(&app.world); let focused = windows.iter().any(|window| window.focused); match config.update_mode(focused) { - UpdateMode::Continuous => *control_flow = ControlFlow::Poll, + UpdateMode::Continuous => { + event_loop.set_control_flow(ControlFlow::Poll); + } UpdateMode::Reactive { wait } | UpdateMode::ReactiveLowPower { wait } => { if let Some(next) = runner_state.last_update.checked_add(*wait) { runner_state.scheduled_update = Some(next); - *control_flow = ControlFlow::WaitUntil(next); + event_loop.set_control_flow(ControlFlow::WaitUntil(next)); } else { runner_state.scheduled_update = None; - *control_flow = ControlFlow::Wait; + event_loop.set_control_flow(ControlFlow::Wait); } } } @@ -873,13 +829,13 @@ pub fn winit_runner(mut app: App) { { if redraw_event_reader.read(app_redraw_events).last().is_some() { runner_state.redraw_requested = true; - *control_flow = ControlFlow::Poll; + event_loop.set_control_flow(ControlFlow::Poll); } } if let Some(app_exit_events) = app.world.get_resource::>() { if app_exit_event_reader.read(app_exit_events).last().is_some() { - *control_flow = ControlFlow::Exit; + event_loop.exit(); } } } @@ -930,9 +886,24 @@ pub fn winit_runner(mut app: App) { }; trace!("starting winit event loop"); - if return_from_run { - run_return(&mut event_loop, event_handler); - } else { - run(event_loop, event_handler); + if let Err(err) = event_loop.run(event_handler) { + error!("winit event loop returned an error: {err}"); } } + +fn react_to_resize( + window: &mut Mut<'_, Window>, + size: winit::dpi::PhysicalSize, + event_writers: &mut WindowAndInputEventWriters<'_>, + window_entity: Entity, +) { + window + .resolution + .set_physical_resolution(size.width, size.height); + + event_writers.window_resized.send(WindowResized { + window: window_entity, + width: window.width(), + height: window.height(), + }); +} diff --git a/crates/bevy_winit/src/system.rs b/crates/bevy_winit/src/system.rs index c3f3c49a36fbc..00910dc923e28 100644 --- a/crates/bevy_winit/src/system.rs +++ b/crates/bevy_winit/src/system.rs @@ -27,7 +27,7 @@ use crate::{ self, convert_enabled_buttons, convert_window_level, convert_window_theme, convert_winit_theme, }, - get_best_videomode, get_fitting_videomode, WinitWindows, + get_best_videomode, get_fitting_videomode, WindowAndInputEventWriters, WinitWindows, }; /// Creates new windows on the [`winit`] backend for each entity with a newly-added @@ -138,6 +138,7 @@ pub struct CachedWindow { pub(crate) fn changed_windows( mut changed_windows: Query<(Entity, &mut Window, &mut CachedWindow), Changed>, winit_windows: NonSendMut, + mut event_writers: WindowAndInputEventWriters<'_>, ) { for (entity, mut window, mut cache) in &mut changed_windows { if let Some(winit_window) = winit_windows.get_window(entity) { @@ -174,7 +175,9 @@ pub(crate) fn changed_windows( window.resolution.physical_width(), window.resolution.physical_height(), ); - winit_window.set_inner_size(physical_size); + if let Some(size_now) = winit_window.request_inner_size(physical_size) { + crate::react_to_resize(&mut window, size_now, &mut event_writers, entity); + } } if window.physical_cursor_position() != cache.window.physical_cursor_position() { @@ -298,10 +301,10 @@ pub(crate) fn changed_windows( } if window.ime_position != cache.window.ime_position { - winit_window.set_ime_position(LogicalPosition::new( - window.ime_position.x, - window.ime_position.y, - )); + winit_window.set_ime_cursor_area( + LogicalPosition::new(window.ime_position.x, window.ime_position.y), + PhysicalSize::new(10, 10), + ); } if window.window_theme != cache.window.window_theme { diff --git a/crates/bevy_winit/src/web_resize.rs b/crates/bevy_winit/src/web_resize.rs index a53075dea3883..4a43bfb911b05 100644 --- a/crates/bevy_winit/src/web_resize.rs +++ b/crates/bevy_winit/src/web_resize.rs @@ -31,7 +31,7 @@ fn canvas_parent_resize_event_handler( ) { for event in resize_events.receiver.try_iter() { if let Some(window) = winit_windows.get_window(event.window) { - window.set_inner_size(event.size); + let _ = window.request_inner_size(event.size); } } } diff --git a/crates/bevy_winit/src/winit_config.rs b/crates/bevy_winit/src/winit_config.rs index d6b22ecf21535..b91e25d340afa 100644 --- a/crates/bevy_winit/src/winit_config.rs +++ b/crates/bevy_winit/src/winit_config.rs @@ -4,32 +4,6 @@ use bevy_utils::Duration; /// Settings for the [`WinitPlugin`](super::WinitPlugin). #[derive(Debug, Resource)] pub struct WinitSettings { - /// Controls how the [`EventLoop`](winit::event_loop::EventLoop) is deployed. - /// - /// - If this value is set to `false` (default), [`run`] is called, and exiting the loop will - /// terminate the program. - /// - If this value is set to `true`, [`run_return`] is called, and exiting the loop will - /// return control to the caller. - /// - /// **Note:** This cannot be changed while the loop is running. `winit` also discourages use of - /// `run_return`. - /// - /// # Supported platforms - /// - /// `run_return` is only available on the following `target_os` environments: - /// - `windows` - /// - `macos` - /// - `linux` - /// - `freebsd` - /// - `openbsd` - /// - `netbsd` - /// - `dragonfly` - /// - /// The runner will panic if this is set to `true` on other platforms. - /// - /// [`run`]: https://docs.rs/winit/latest/winit/event_loop/struct.EventLoop.html#method.run - /// [`run_return`]: https://docs.rs/winit/latest/winit/platform/run_return/trait.EventLoopExtRunReturn.html#tymethod.run_return - pub return_from_run: bool, /// Determines how frequently the application can update when it has focus. pub focused_mode: UpdateMode, /// Determines how frequently the application can update when it's out of focus. @@ -47,7 +21,6 @@ impl WinitSettings { unfocused_mode: UpdateMode::ReactiveLowPower { wait: Duration::from_secs_f64(1.0 / 60.0), // 60Hz }, - ..Default::default() } } @@ -63,7 +36,6 @@ impl WinitSettings { unfocused_mode: UpdateMode::ReactiveLowPower { wait: Duration::from_secs(60), }, - ..Default::default() } } @@ -81,7 +53,6 @@ impl WinitSettings { impl Default for WinitSettings { fn default() -> Self { WinitSettings { - return_from_run: false, focused_mode: UpdateMode::Continuous, unfocused_mode: UpdateMode::Continuous, } diff --git a/crates/bevy_winit/src/winit_windows.rs b/crates/bevy_winit/src/winit_windows.rs index bd88b26f42560..da4024aef8f0d 100644 --- a/crates/bevy_winit/src/winit_windows.rs +++ b/crates/bevy_winit/src/winit_windows.rs @@ -194,7 +194,7 @@ impl WinitWindows { use winit::platform::web::WindowExtWebSys; if window.canvas.is_none() { - let canvas = winit_window.canvas(); + let canvas = winit_window.canvas().expect("Failed to retrieve canvas."); let window = web_sys::window().unwrap(); let document = window.document().unwrap(); diff --git a/examples/2d/2d_gizmos.rs b/examples/2d/2d_gizmos.rs index 196e73f1f5884..d3dcd7c960f6a 100644 --- a/examples/2d/2d_gizmos.rs +++ b/examples/2d/2d_gizmos.rs @@ -66,10 +66,10 @@ fn update_config( keyboard: Res>, time: Res