From 3900b48c88cf2ba66ca970ec007fb63002893c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Fri, 3 Feb 2023 16:41:39 +0000 Subject: [PATCH] update winit to 0.28 (#7480) # Objective - Update winit to 0.28 ## Solution - Small API change - A security advisory has been added for a unmaintained crate used by a dependency of winit build script for wayland I didn't do anything for Android support in this PR though it should be fixable, it should be done in a separate one, maybe https://github.com/bevyengine/bevy/pull/6830 --- ## Changelog - `window.always_on_top` has been removed, you can now use `window.window_level` ## Migration Guide before: ```rust app.new() .add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { always_on_top: true, ..default() }), ..default() })); ``` after: ```rust app.new() .add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { window_level: bevy::window::WindowLevel::AlwaysOnTop, ..default() }), ..default() })); ``` --- crates/bevy_asset/Cargo.toml | 6 ++-- crates/bevy_asset/src/io/android_asset_io.rs | 5 +++- crates/bevy_derive/src/bevy_main.rs | 8 ++--- crates/bevy_internal/Cargo.toml | 5 ---- crates/bevy_internal/src/lib.rs | 3 -- crates/bevy_window/src/window.rs | 31 ++++++++++++++++++-- crates/bevy_winit/Cargo.toml | 6 +++- crates/bevy_winit/src/converters.rs | 10 ++++++- crates/bevy_winit/src/lib.rs | 23 +++++++++++++-- crates/bevy_winit/src/system.rs | 9 ++++-- crates/bevy_winit/src/winit_windows.rs | 4 ++- deny.toml | 10 ++----- examples/ui/window_fallthrough.rs | 2 +- examples/window/window_settings.rs | 26 ++++++++-------- 14 files changed, 101 insertions(+), 47 deletions(-) diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index c64bb610bf939..191b4a9d7df94 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -33,15 +33,15 @@ fastrand = "1.7.0" notify = { version = "5.0.0", optional = true } parking_lot = "0.12.1" +[target.'cfg(target_os = "android")'.dependencies] +bevy_winit = { path = "../bevy_winit", version = "0.9.0" } + [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = { version = "0.2" } web-sys = { version = "0.3", features = ["Request", "Window", "Response"] } wasm-bindgen-futures = "0.4" js-sys = "0.3" -[target.'cfg(target_os = "android")'.dependencies] -ndk-glue = { version = "0.7" } - [dev-dependencies] futures-lite = "1.4.0" tempfile = "3.2.0" diff --git a/crates/bevy_asset/src/io/android_asset_io.rs b/crates/bevy_asset/src/io/android_asset_io.rs index 4b5f41b140fc2..5bd583aee2092 100644 --- a/crates/bevy_asset/src/io/android_asset_io.rs +++ b/crates/bevy_asset/src/io/android_asset_io.rs @@ -32,7 +32,10 @@ impl AndroidAssetIo { impl AssetIo for AndroidAssetIo { fn load_path<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result, AssetIoError>> { Box::pin(async move { - let asset_manager = ndk_glue::native_activity().asset_manager(); + let asset_manager = bevy_winit::ANDROID_APP + .get() + .expect("Bevy must be setup with the #[bevy_main] macro on Android") + .asset_manager(); let mut opened_asset = asset_manager .open(&CString::new(path.to_str().unwrap()).unwrap()) .ok_or(AssetIoError::NotFound(path.to_path_buf()))?; diff --git a/crates/bevy_derive/src/bevy_main.rs b/crates/bevy_derive/src/bevy_main.rs index fc5ea60bb0a1f..36773c214b89a 100644 --- a/crates/bevy_derive/src/bevy_main.rs +++ b/crates/bevy_derive/src/bevy_main.rs @@ -10,11 +10,11 @@ pub fn bevy_main(_attr: TokenStream, item: TokenStream) -> TokenStream { ); TokenStream::from(quote! { - // use ndk-glue macro to create an activity: https://github.com/rust-mobile/ndk-glue/tree/main/ndk-macro + #[no_mangle] #[cfg(target_os = "android")] - #[cfg_attr(target_os = "android", bevy::ndk_glue::main(backtrace = "on", ndk_glue = "bevy::ndk_glue"))] - fn android_main() { - main() + fn android_main(android_app: bevy::winit::AndroidApp) { + let _ = bevy::winit::ANDROID_APP.set(android_app); + main(); } #[no_mangle] diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index da264c92a8dfc..522c67b4a8832 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -107,8 +107,3 @@ bevy_text = { path = "../bevy_text", optional = true, version = "0.9.0" } bevy_ui = { path = "../bevy_ui", optional = true, version = "0.9.0" } bevy_winit = { path = "../bevy_winit", optional = true, version = "0.9.0" } bevy_gilrs = { path = "../bevy_gilrs", optional = true, version = "0.9.0" } - -[target.'cfg(target_os = "android")'.dependencies] -# This version *must* be the same as the version used by winit, -# or Android will break: https://github.com/rust-windowing/winit#android -ndk-glue = {version = "0.7", features = ["logger"]} diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index a1e42d64a12fe..f1bcfa57a2b3a 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -172,6 +172,3 @@ pub mod dynamic_plugin { //! Dynamic linking of plugins pub use bevy_dynamic_plugin::*; } - -#[cfg(target_os = "android")] -pub use ndk_glue; diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index 74d91ae115d8c..28d9527267c3a 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -141,7 +141,7 @@ pub struct Window { /// ## Platform-specific /// /// - iOS / Android / Web / Wayland: Unsupported. - pub always_on_top: bool, + pub window_level: WindowLevel, /// The "html canvas" element selector. /// /// If set, this selector will be used to find a matching html canvas element, @@ -205,7 +205,7 @@ impl Default for Window { decorations: true, transparent: false, focused: true, - always_on_top: false, + window_level: Default::default(), fit_canvas_to_parent: false, prevent_default_event_handling: true, canvas: None, @@ -800,3 +800,30 @@ pub enum WindowMode { /// Creates a fullscreen window that uses the maximum supported size. Fullscreen, } + +/// A window level groups windows with respect to their z-position. +/// +/// The relative ordering between windows in different window levels is fixed. +/// The z-order of a window within the same window level may change dynamically on user interaction. +/// +/// ## Platform-specific +/// +/// - **iOS / Android / Web / Wayland:** Unsupported. +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)] +#[cfg_attr( + feature = "serialize", + derive(serde::Serialize, serde::Deserialize), + reflect(Serialize, Deserialize) +)] +#[reflect(Debug, PartialEq)] +pub enum WindowLevel { + /// The window will always be below normal windows. + /// + /// This is useful for a widget-based app. + AlwaysOnBottom, + /// The default. + #[default] + Normal, + /// The window will always be on top of normal windows. + AlwaysOnTop, +} diff --git a/crates/bevy_winit/Cargo.toml b/crates/bevy_winit/Cargo.toml index 96864623f1113..49e83f0872781 100644 --- a/crates/bevy_winit/Cargo.toml +++ b/crates/bevy_winit/Cargo.toml @@ -23,10 +23,14 @@ bevy_window = { path = "../bevy_window", version = "0.9.0" } bevy_utils = { path = "../bevy_utils", version = "0.9.0" } # other -winit = { version = "0.27", default-features = false } +winit = { version = "0.28", default-features = false } approx = { version = "0.5", default-features = false } raw-window-handle = "0.5" +[target.'cfg(target_os = "android")'.dependencies] +winit = { version = "0.28", default-features = false, features = ["android-native-activity"] } +once_cell = "1.11" + [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = { version = "0.2" } web-sys = "0.3" diff --git a/crates/bevy_winit/src/converters.rs b/crates/bevy_winit/src/converters.rs index 2e6d0cf7ce3dc..28301f48da520 100644 --- a/crates/bevy_winit/src/converters.rs +++ b/crates/bevy_winit/src/converters.rs @@ -5,7 +5,7 @@ use bevy_input::{ ButtonState, }; use bevy_math::Vec2; -use bevy_window::CursorIcon; +use bevy_window::{CursorIcon, WindowLevel}; pub fn convert_keyboard_input(keyboard_input: &winit::event::KeyboardInput) -> KeyboardInput { KeyboardInput { @@ -266,3 +266,11 @@ pub fn convert_cursor_icon(cursor_icon: CursorIcon) -> winit::window::CursorIcon CursorIcon::RowResize => winit::window::CursorIcon::RowResize, } } + +pub fn convert_window_level(window_level: WindowLevel) -> winit::window::WindowLevel { + match window_level { + WindowLevel::AlwaysOnBottom => winit::window::WindowLevel::AlwaysOnBottom, + WindowLevel::Normal => winit::window::WindowLevel::Normal, + WindowLevel::AlwaysOnTop => winit::window::WindowLevel::AlwaysOnTop, + } +} diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 544db1b6f268c..67d77d00b2dd6 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -31,21 +31,40 @@ use bevy_window::{ WindowScaleFactorChanged, }; +#[cfg(target_os = "android")] +pub use winit::platform::android::activity::AndroidApp; + use winit::{ event::{self, DeviceEvent, Event, StartCause, WindowEvent}, - event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget}, + event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopWindowTarget}, }; use crate::system::WinitWindowInfo; #[cfg(target_arch = "wasm32")] use crate::web_resize::{CanvasParentResizeEventChannel, CanvasParentResizePlugin}; +#[cfg(target_os = "android")] +pub static ANDROID_APP: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + #[derive(Default)] pub struct WinitPlugin; impl Plugin for WinitPlugin { fn build(&self, app: &mut App) { - let event_loop = EventLoop::new(); + let mut event_loop_builder = EventLoopBuilder::<()>::with_user_event(); + + #[cfg(target_os = "android")] + { + use winit::platform::android::EventLoopBuilderExtAndroid; + event_loop_builder.with_android_app( + ANDROID_APP + .get() + .expect("Bevy must be setup with the #[bevy_main] macro on Android") + .clone(), + ); + } + + let event_loop = event_loop_builder.build(); app.insert_non_send_resource(event_loop); app.init_non_send_resource::() diff --git a/crates/bevy_winit/src/system.rs b/crates/bevy_winit/src/system.rs index 708c803451a64..8f5bdeaf05cf5 100644 --- a/crates/bevy_winit/src/system.rs +++ b/crates/bevy_winit/src/system.rs @@ -19,7 +19,10 @@ use winit::{ #[cfg(target_arch = "wasm32")] use crate::web_resize::{CanvasParentResizeEventChannel, WINIT_CANVAS_SELECTOR}; -use crate::{converters, get_best_videomode, get_fitting_videomode, WinitWindows}; +use crate::{ + converters::{self, convert_window_level}, + get_best_videomode, get_fitting_videomode, WinitWindows, +}; #[cfg(target_arch = "wasm32")] use bevy_ecs::system::ResMut; @@ -262,8 +265,8 @@ pub(crate) fn changed_window( winit_window.focus_window(); } - if window.always_on_top != previous.always_on_top { - winit_window.set_always_on_top(window.always_on_top); + if window.window_level != previous.window_level { + winit_window.set_window_level(convert_window_level(window.window_level)); } // Currently unsupported changes diff --git a/crates/bevy_winit/src/winit_windows.rs b/crates/bevy_winit/src/winit_windows.rs index 25ac5e40b780a..4c690afaaba01 100644 --- a/crates/bevy_winit/src/winit_windows.rs +++ b/crates/bevy_winit/src/winit_windows.rs @@ -8,6 +8,8 @@ use winit::{ monitor::MonitorHandle, }; +use crate::converters::convert_window_level; + #[derive(Debug, Default)] pub struct WinitWindows { pub windows: HashMap, @@ -65,7 +67,7 @@ impl WinitWindows { }; winit_window_builder = winit_window_builder - .with_always_on_top(window.always_on_top) + .with_window_level(convert_window_level(window.window_level)) .with_resizable(window.resizable) .with_decorations(window.decorations) .with_transparent(window.transparent); diff --git a/deny.toml b/deny.toml index 4bb93186c686a..f0a41621700fa 100644 --- a/deny.toml +++ b/deny.toml @@ -7,6 +7,7 @@ yanked = "deny" notice = "deny" ignore = [ "RUSTSEC-2020-0056", # from cpal v0.14.1 - unmaintained - https://github.com/koute/stdweb/issues/403 + "RUSTSEC-2022-0048", # from xml-rs 0.8.4 - unmaintained - it's used in a build script of winit ] [licenses] @@ -36,16 +37,11 @@ highlight = "all" skip = [ { name = "ndk-sys", version = "0.3" }, # from rodio v0.16.0 { name = "ndk", version = "0.6" }, # from rodio v0.16.0 - { name = "raw-window-handle", version = "0.4" }, # from winit v0.27.4 { name = "nix", version = "0.23" }, # from cpal v0.14.1 + { name = "redox_syscall", version = "0.2" }, # from notify v5.1.0 { name = "rustc_version", version = "0.2" }, # from postcard v1.0.2 { name = "semver", version = "0.9" }, # from postcard v1.0.2 - { name = "windows_aarch64_msvc", version = "0.36" }, # from notify v5.0.0 - { name = "windows_i686_gnu", version = "0.36" }, # from notify v5.0.0 - { name = "windows_i686_msvc", version = "0.36" }, # from notify v5.0.0 - { name = "windows_x86_64_gnu", version = "0.36" }, # from notify v5.0.0 - { name = "windows_x86_64_msvc", version = "0.36" }, # from notify v5.0.0 - { name = "windows-sys", version = "0.36" }, # from notify v5.0.0 + { name = "windows-sys", version = "0.42" }, # from notify v5.1.0 { name = "windows", version = "0.37" }, # from rodio v0.16.0 { name = "windows_aarch64_msvc", version = "0.37" }, # from rodio v0.16.0 { name = "windows_i686_gnu", version = "0.37" }, # from rodio v0.16.0 diff --git a/examples/ui/window_fallthrough.rs b/examples/ui/window_fallthrough.rs index 82cc275501954..d2b4459be4031 100644 --- a/examples/ui/window_fallthrough.rs +++ b/examples/ui/window_fallthrough.rs @@ -11,7 +11,7 @@ fn main() { // Set the window's parameters, note we're setting the window to always be on top. transparent: true, decorations: true, - always_on_top: true, + window_level: bevy::window::WindowLevel::AlwaysOnTop, ..default() }), ..default() diff --git a/examples/window/window_settings.rs b/examples/window/window_settings.rs index 7d914081cfec1..47867e4f7dc8c 100644 --- a/examples/window/window_settings.rs +++ b/examples/window/window_settings.rs @@ -4,7 +4,7 @@ use bevy::{ diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, prelude::*, - window::{CursorGrabMode, PresentMode}, + window::{CursorGrabMode, PresentMode, WindowLevel}, }; fn main() { @@ -28,7 +28,7 @@ fn main() { .add_system(toggle_cursor) .add_system(toggle_vsync) .add_system(cycle_cursor_icon) - .add_system(toggle_always_on_top) + .add_system(switch_level) .run(); } @@ -47,23 +47,23 @@ fn toggle_vsync(input: Res>, mut windows: Query<&mut Window>) { } } -/// This system toggles whether the window is always on top when pressing the T button -/// You'll notice it won't be covered by other windows. +/// This system switches the window level when pressing the T button +/// You'll notice it won't be covered by other windows, or will be covered by all the other +/// windows depending on the level. /// /// This feature only works on some platforms. Please check the -/// [documentation](https://docs.rs/bevy/latest/bevy/prelude/struct.WindowDescriptor.html#structfield.always_on_top) +/// [documentation](https://docs.rs/bevy/latest/bevy/prelude/struct.Window.html#structfield.window_level) /// for more details. -fn toggle_always_on_top(input: Res>, mut windows: Query<&mut Window>) { +fn switch_level(input: Res>, mut windows: Query<&mut Window>) { if input.just_pressed(KeyCode::T) { let mut window = windows.single_mut(); - window.always_on_top = !window.always_on_top; - - if window.always_on_top { - info!("LOCKING WINDOW ON TOP"); - } else { - info!("UNLOCKING WINDOW"); - } + window.window_level = match window.window_level { + WindowLevel::AlwaysOnBottom => WindowLevel::Normal, + WindowLevel::Normal => WindowLevel::AlwaysOnTop, + WindowLevel::AlwaysOnTop => WindowLevel::AlwaysOnBottom, + }; + info!("WINDOW_LEVEL: {:?}", window.window_level); } }