macOS regresssion: new window starts on top of fullscreen window
emilk opened this issue · 6 comments
Reproduce: Run VSCode in fullscreen mode, and in the VSCode terminal enter cargo run --example window
(in the winit
repo).
Expected (and actual in winit 0.24):
The view changes to the desktop and the winit window opens there.
Actual:
The winit window pops up over the fullscreen VSCode, and then the view changes to the desktop (where there is no window).
When did this break?
Work-arounds
Add the following code to after you create the event loop, but before creating your window:
#[cfg(target_os = "macos")]
unsafe {
// work-around for https://github.com/rust-windowing/winit/issues/2051
use cocoa::appkit::NSApplication as _;
cocoa::appkit::NSApp().setActivationPolicy_(
cocoa::appkit::NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
);
}
This is really an issue with the way that winit
encourages creating windows before -applicationDidFinishLaunching:
; ideally you should create your window on Event::NewEvents(StartCause::Init)
:
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent, StartCause},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let mut window = None;
event_loop.run(move |event, event_loop, control_flow| {
*control_flow = ControlFlow::Wait;
println!("{:?}", event);
match event {
Event::NewEvents(StartCause::Init) => {
window = Some(WindowBuilder::new()
.with_title("A fantastic window!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.build(&event_loop)
.unwrap());
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
} if window_id == window.as_ref().unwrap().id() => *control_flow = ControlFlow::Exit,
Event::MainEventsCleared => {
window.as_ref().unwrap().request_redraw();
}
_ => (),
}
});
}
But if that is not possible, you can temporarily add the following after EventLoop::new
and before creating your window, to revert to the behaviour before #1922:
unsafe {
use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicy::*};
let ns_app = NSApp();
ns_app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
}
I can confirm that adding
unsafe {
use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicy::*};
let ns_app = NSApp();
ns_app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
}
to the top of the app fixes the problem! Thanks for that work-around!
I can confirm that your sample code works on macOS and fixed the window behaviour.
With regard to:
Ideally you should create your window on
Event::NewEvents(StartCause::Init)
:
I think an update to the primary usage example would help to make this clear. See crates.io - this is where I started.
Also, the idea to redraw every time MainEventsCleared
is not in the example:
Event::MainEventsCleared => {
window.as_ref().unwrap().request_redraw();
}
On the surface, this looks a little redundant. Can it be explained, and also added to the example.
I think the idea of creating the window from within the loop is a good one, but other libraries (like glium
) might need some time to work this into their code.
So essentially (like the title suggests) this should most likely be marked as a type: bug and be fixed accordingly.
Also, the idea to redraw every time
MainEventsCleared
is not in the example:
On the surface, this looks a little redundant
I just quickly copied the window
example when making that post, request_redraw
is not related to this.
be marked as a type: bug and be fixed accordingly.
Correct.
I may try to take at stab at it at some point, but others should feel welcome!