Conversation
This moves the application launch from the beginning of `EventLoop::run_app` to `EventLoop::new`, which: - Feels more consistent, we now emit `new_events(StartCause::Init)` at the beginning of `run_app_on_demand` instead of conditionally depending on if the application has launched or not. - Would allow us to bring back `event_loop.create_window` in some form on macOS, since the application would now be launched between `EventLoop::new` and `EventLoop::run_app`. This differs semantically from iOS where we must still launch the application in `EventLoop::run_app`, but iOS is the special snowflake here, the other desktop platforms' are semantically launched after `EventLoop::new`. Doing it this way also matches what GLFW's init function does.
| // Run `finishLaunching` just in case it works. | ||
| app.finishLaunching(); | ||
| // Now _ideally_, calling `finishLaunching` should be enough for the application to, you | ||
| // know, launch (create the a dock icon etc.), but unfortunately, this doesn't happen for | ||
| // various godforsaken reasons... The only way to make the application properly launch is by | ||
| // calling `NSApplication::run`. | ||
| // | ||
| // So we check if the application hasn't finished launching, and if it hasn't, we run it | ||
| // once to finish it. | ||
| // | ||
| // This is _very_ important, there's a _lot_ of weird and subtle state that requires that | ||
| // the application is launched properly, including window creation, the menu bar, | ||
| // activation, see: | ||
| // - https://github.com/rust-windowing/winit/pull/1903 | ||
| // - https://github.com/rust-windowing/winit/pull/1922 | ||
| // - https://github.com/rust-windowing/winit/issues/2238 | ||
| // - https://github.com/rust-windowing/winit/issues/2051 | ||
| // - https://github.com/rust-windowing/winit/issues/2087 | ||
| // - https://developer.apple.com/forums/thread/772169 | ||
| // | ||
| // This approach is similar to what other cross-platform windowing libraries do (except that | ||
| // we do it without a delegate to allow users to override that): | ||
| // - GLFW delegate: https://github.com/glfw/glfw/blob/3.4/src/cocoa_init.m#L439-L443 | ||
| // - GLFW launch: https://github.com/glfw/glfw/blob/3.4/src/cocoa_init.m#L634-L635 | ||
| // - FLTK delegate: https://github.com/fltk/fltk/blob/release-1.4.4/src/Fl_cocoa.mm#L1604-L1607 | ||
| // - FLTK launch: https://github.com/fltk/fltk/blob/release-1.4.4/src/Fl_cocoa.mm#L1903-L1919 | ||
| // - Stackoverflow issue: https://stackoverflow.com/questions/48020222/how-to-make-nsapp-run-not-block/67626393#67626393 |
There was a problem hiding this comment.
I am a bit furious (at both myself and Apple) about this, I've been oblivious to this for years (even though I vividly recall starting at GLFW's initialization code for what must've been hours, and concluding "they must just not have fixed this issue"), it's only ~half a year ago that I connected the dots and found out that you actually can launch the application!
Had I known this way back then, I wouldn't have pushed so hard for removing Window::new / event_loop.create_window :/
(Those are still problematic on iOS, but that's a secondary citizen that needs special care, so I'd be more fine with excluding that from such considerations).
There was a problem hiding this comment.
Window::new requires event loop anyway, so it's irrelevant where it is.
|
CC @kchibisov @daxpedda with this, it might make sense to reintroduce a desktop/web-specific impl EventLoop {
#[cfg(not(any(android_platform, ios_platform)))]
pub fn create_window_desktop(
&self,
window_attributes: WindowAttributes,
) -> Result<Box<dyn Window>, RequestError> {
self.event_loop.window_target().create_window(window_attributes)
}
}I suspect that would solve a lot of the issues users have in #3626 and #3877, most people don't need their thing to run on Android and iOS. |
As per discussion, I'd be fine if you return impl EventLoop {
#[cfg(not(any(android_platform, ios_platform)))]
pub fn create_surface(
&self,
window_attributes: WindowAttributes,
) -> Result<Box<dyn Surface>, RequestError> {
self.event_loop.window_target().create_window(window_attributes)
}
}
pub trait Surface {
fn window_handle();
fn surface_size() ->
}There're some APIs in the fly #4264 . |
This moves the application launch from the beginning of
EventLoop::run_apptoEventLoop::new, which:new_events(StartCause::Init)at the beginning ofrun_app_on_demandinstead of conditionally depending on if the application has launched or not.event_loop.create_windowin some form on macOS, since the application would now be launched betweenEventLoop::newandEventLoop::run_app. See Deprecate window creation with stale event loop #3447 for why we removed it originally.This differs semantically from iOS where we must still launch the application in
EventLoop::run_app, but iOS is the special snowflake here, the other desktop platforms' are semantically launched afterEventLoop::new. Doing it this way also matches what GLFW's init function does.changelogmodule if knowledge of this change could be valuable to users