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

macOS regresssion: new window starts on top of fullscreen window #2051

Closed
emilk opened this issue Nov 4, 2021 · 6 comments
Closed

macOS regresssion: new window starts on top of fullscreen window #2051

emilk opened this issue Nov 4, 2021 · 6 comments
Labels
B - bug Dang, that shouldn't have happened DS - macos H - help wanted Someone please save us

Comments

@emilk
Copy link
Contributor

emilk commented Nov 4, 2021

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,
        );
    }
@madsmtm
Copy link
Member

madsmtm commented Nov 4, 2021

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
Copy link
Contributor Author

emilk commented Nov 4, 2021

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!

@wduminy
Copy link

wduminy commented Jan 10, 2022

@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.

@wduminy
Copy link

wduminy commented Jan 16, 2022

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.

@madsmtm madsmtm added H - help wanted Someone please save us B - bug Dang, that shouldn't have happened and removed C - needs investigation Issue must be confirmed and researched labels Jan 16, 2022
@madsmtm
Copy link
Member

madsmtm commented Jan 16, 2022

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!

@madsmtm
Copy link
Member

madsmtm commented Aug 15, 2024

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

@madsmtm madsmtm closed this as completed Aug 15, 2024
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 H - help wanted Someone please save us
Development

No branches or pull requests

4 participants