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: create unfocused window #3072

Closed
rparrett opened this issue Aug 30, 2023 · 7 comments
Closed

macos: create unfocused window #3072

rparrett opened this issue Aug 30, 2023 · 7 comments
Labels
DS - macos F - question There's no such thing as a stupid one

Comments

@rparrett
Copy link

rparrett commented Aug 30, 2023

Using macos 13.4.1.
Testing with the main branch.

I'd like to create a single window that begins its life visible but unfocused, never stealing focus.

with_active(false) seems like it should accomplish this, but with that, the new window still appears on top of every other window, reacts to key presses, etc.

Even with .with_window_level(winit::window::WindowLevel::AlwaysOnBottom) and .with_visible(false), the window seems to take focus away from the currently focused window, interrupting typing (but doesn't seem to react to keypresses itself).

Repro:

sleep 5 && cargo run
# now before the window opens, switch back to a text editor
# and attempt to type some things without being interrupted by the new window stealing focus
use simple_logger::SimpleLogger;
use winit::{
    event::{Event, WindowEvent},
    event_loop::EventLoop,
    window::WindowBuilder,
};

fn main() {
    SimpleLogger::new().init().unwrap();

    let event_loop = EventLoop::new();

    let window = WindowBuilder::new()
        .with_active(false)
        .build(&event_loop)
        .unwrap();

    event_loop.run(move |event, _, control_flow| {
        control_flow.set_wait();

        match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                window_id,
            } if window_id == window.id() => control_flow.set_exit(),
            _ => (),
        }
    });
}
@madsmtm
Copy link
Member

madsmtm commented Aug 30, 2023

Have you looked through the platform-specific extensions in winit::platform::macos? I'm not sure exactly what you want, but it might be possible with a combination of the options in there (in particular see EventLoopBuilderExtMacOS, it allows you to set the activation policy and such).

@madsmtm madsmtm added F - question There's no such thing as a stupid one DS - macos labels Aug 30, 2023
@rparrett
Copy link
Author

rparrett commented Aug 30, 2023

Thanks, I hadn't seen that. Unfortunately even with

let event_loop = EventLoopBuilder::new()
    .with_activation_policy(ActivationPolicy::Accessory)
    .build();

The new window steals focus.

I realize that my report is a bit all-over-the-place. (I just did some editing there) To clarify, the behavior I'm after is:

  • have terminal open
  • cargo run
  • new window appears behind the terminal
  • focus was never stolen from the terminal

And in every other way, I would like for it to be normal window. Any mention of the status bar is me not realizing this is a separate concept from focus in macos.

with_active's docs would seem to describe this behavior, but it's possible that I'm not understanding how focus works on this platform.

@madsmtm
Copy link
Member

madsmtm commented Aug 31, 2023

Hmm, could you try following the advice in the README, and create your window inside Event::NewEvents(StartCause::Init)?

@madsmtm
Copy link
Member

madsmtm commented Aug 31, 2023

And also try .with_activate_ignoring_other_apps(false).

@rparrett
Copy link
Author

rparrett commented Aug 31, 2023

Ooh, thank you!

let event_loop = EventLoopBuilder::new()
    .with_activate_ignoring_other_apps(false)
    .build();

Does seem to make the situation better. The docs for with_activate_ignoring_other_apps are melting my brain slightly, but I wonder if this window is considered a child of the terminal or something? Maybe I can contrive some way to test this without launching from a terminal.

Hmm, could you try following the advice in the README, and create your window inside Event::NewEvents(StartCause::Init)?

I hadn't tried that because outside of this modified winit example the windows are being created within the event loop. But for thoroughness I checked that out and a workaround mentioned in #2051 and with_active(false) still acts in the surprising-to-me way.

@rparrett
Copy link
Author

rparrett commented Aug 31, 2023

I wonder if this window is considered a child of the terminal or something? Maybe I can contrive some way to test this without launching from a terminal.

with_active(false/true) does seem to work as expected when invoked with something like

echo "./target/debug/examples/unfocused" | at now

So I guess this is something close to what I was guessing just above and there's no bug here.

Really appreciate the help.

@madsmtm
Copy link
Member

madsmtm commented Aug 31, 2023

The reason we set with_activate_ignoring_other_apps to true by default btw is because it provides a better development experience when not using Xcode - ideally, graphical applications should be packaged up in a bundle, and then they work much better with regards to activation.

Glad that you figured it out though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DS - macos F - question There's no such thing as a stupid one
Development

No branches or pull requests

2 participants