winitrequires control over the principal class. You must create the event loop before other parts of your application initialize NSApplication
Description
Background
I built a program combine Qt/Qml and bevy , and I can run it normally on ubuntu system , but when run it on macos, it output a error, and I think this is a platform related problem. So I hope to know how to solve it.
project address
https://github.com/dezbracaty/BevyQml
Information
After running App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, animate_cube) .run();
It crash and output :
2024-07-02T05:56:27.686954Z INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "MacOS 15.0 ", kernel: "24.0.0", cpu: "Apple M1 Pro", core_count: "10", memory: "16.0 GiB" } thread '
macOS version
Macos 15 beta2
rustc 1.79.0 (129f3b996 2024-06-10)
Winit version
cargo tree -i winit winit v0.30.3 ├── accesskit_winit v0.21.1 │ └── bevy_winit v0.14.0-dev (https://github.com/bevyengine/bevy?branch=main#f607be87) │ └── bevy_internal v0.14.0-dev (https://github.com/bevyengine/bevy?branch=main#f607be87) │ └── bevy v0.14.0-dev (https://github.com/bevyengine/bevy?branch=main#f607be87) │ └── qml_minimal v0.1.0 (/Users/allen/Projects/RustProjects/BevyQml/bevyQml/rust) └── bevy_winit v0.14.0-dev (https://github.com/bevyengine/bevy?branch=main#f607be87) (*)
I've encountered this recently and found a solution for my case that involved using Winit through Slint and tray-icon.
Under macOS, the windowing event loop must be started from the main thread, as otherwise AppKit crashes the process. Furthermore, it must also be started before any other such constructs, as otherwise Winit crashes the process on a panic here:
https://github.com/rust-windowing/winit/blob/dfea49f48850670cdfe3dc91949a9f8f2e267a38/src/platform_impl/apple/appkit/event_loop.rs#L212-L223
where it checks that the returned class is the correct one instead of working on incorrect data, most probably due to AppKit global state.
I was able to fix my case by ensuring Winit's event loop was always started first and before tray-icon's. A similar solution should be possible for you: try to find out what is the other event loop that is running. Temporarily patching Winit locally in order to display context before the aforementioned panic should help for example.
If the other event loop is out of your control, it could be a Bevy-specific issue. I also see that you're using macOS 15 and maybe Winit does not support it yet as it's still in beta: have you tried it under 14.6?
Indeed, the issue is that something is started before EventLoop::new, which means we no longer have control over the NSApplication. I plan to fix this so that Winit doesn't need control over the NSApplication.