Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

winitrequires control over the principal class. You must create the event loop before other parts of your application initialize NSApplication #3772

Open
dezbracaty opened this issue Jul 2, 2024 · 2 comments · May be fixed by #4036
Assignees
Labels
B - bug Dang, that shouldn't have happened DS - macos

Comments

@dezbracaty
Copy link

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 '' panicked at /Users/allen/.cargo/registry/src/index.crates.io-6f17d22bba15001f/winit-0.30.3/src/platform_impl/macos/event_loop.rs:220:13: winitrequires control over the principal class. You must create the event loop before other parts of your application initialize NSApplication note: run withRUST_BACKTRACE=1 environment variable to display a backtrace fatal runtime error: failed to initiate panic, error 5 [1] 33997 abort /Users/allen/Projects/RustProjects/BevyQml/build/bevyQml/example_qml_minimal

image

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) (*)

@dezbracaty dezbracaty added B - bug Dang, that shouldn't have happened DS - macos labels Jul 2, 2024
@PaulDance
Copy link

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:

let mtm = MainThreadMarker::new()
.expect("on macOS, `EventLoop` must be created on the main thread!");
let app: Retained<NSApplication> =
unsafe { msg_send_id![WinitApplication::class(), sharedApplication] };
if !app.is_kind_of::<WinitApplication>() {
panic!(
"`winit` requires control over the principal class. You must create the event \
loop before other parts of your application initialize NSApplication"
);
}

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?

@madsmtm
Copy link
Member

madsmtm commented Sep 11, 2024

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.

@madsmtm madsmtm self-assigned this Sep 11, 2024
madsmtm added a commit that referenced this issue Dec 8, 2024
This is done to avoid order-dependent behavior that you'd otherwise
encounter where `EventLoop::new` had to be called at the beginning of
`fn main` to ensure that Winit's application was the one being
registered as the main application by calling `sharedApplication`.

Fixes #3772.

This should also make it (more) possible to use multiple versions of
Winit in the same application (though that's still untested).

Finally, it should allow the user to override NSApplication themselves
if they need to do that for some reason.
madsmtm added a commit that referenced this issue Dec 8, 2024
This is done to avoid order-dependent behavior that you'd otherwise
encounter where `EventLoop::new` had to be called at the beginning of
`fn main` to ensure that Winit's application was the one being
registered as the main application by calling `sharedApplication`.

Fixes #3772.

This should also make it (more) possible to use multiple versions of
Winit in the same application (though that's still untested).

Finally, it should allow the user to override `NSApplication` themselves
if they need to do that for some reason.
@madsmtm madsmtm linked a pull request Dec 8, 2024 that will close this issue
4 tasks
madsmtm added a commit that referenced this issue Dec 8, 2024
This is done to avoid order-dependent behavior that you'd otherwise
encounter where `EventLoop::new` had to be called at the beginning of
`fn main` to ensure that Winit's application was the one being
registered as the main application by calling `sharedApplication`.

Fixes #3772.

This should also make it (more) possible to use multiple versions of
Winit in the same application (though that's still untested).

Finally, it should allow the user to override `NSApplication` themselves
if they need to do that for some reason.
madsmtm added a commit that referenced this issue Dec 9, 2024
This is done to avoid order-dependent behavior that you'd otherwise
encounter where `EventLoop::new` had to be called at the beginning of
`fn main` to ensure that Winit's application was the one being
registered as the main application by calling `sharedApplication`.

Fixes #3772.

This should also make it (more) possible to use multiple versions of
Winit in the same application (though that's still untested).

Finally, it should allow the user to override `NSApplication` themselves
if they need to do that for some reason.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B - bug Dang, that shouldn't have happened DS - macos
Development

Successfully merging a pull request may close this issue.

3 participants