rust-windowing/winit

macOS regresssion: new window starts on top of fullscreen window

emilk opened this issue · 6 comments

emilk commented

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);
}
emilk commented

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!

@madsmtm

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!

Fixed by #3447 and #3826 (we first deprecated, and now disallow creating windows before the application has been initialized).